5 NPM packages you should consider use in React project

February 08, 2019

I have been working on React project quite some time. There are some limitations and difficulties I encounter during my development. That took me quite some effort to solve it and I found these packages which really help me a lot and make my life more easy.

Following all code example I will use React Hooks (new feature) for demo. If you still don’t know what is it about, you should check it out! Trust me, is worth it!

React Today and Tomorrow and 90% Cleaner React With Hooks

classnames

classnames is a javascript utility that help to join your classes with condititionally. If you work on React, you will know the HTML elements only accept the className in string type. Therefore, for some use case like toggling class in the element is really anoying thing to do. Let’s see example below.

const { useState } = React

const App = () => {  
  const [hide, setHide] = useState(false)  
    
  const handleToggle = () => {  
    setHide(prevHide => !prevHide)    
  }  
    
  return (  
    <div>  
      <p className={`other-class ${hide ? 'hide' : ''}`}>Text to see</p>  
      <button onClick={handleToggle}>Toggle</button>  
    </div>  
  )  
}

ReactDOM.render(<App />, document.getElementById("root"));

As you can see we have to manually check the hide value to return the class name. Of course for this small example is not really a big deal, but can you imagine you have multiple class import in conditionally, is kind of tedious way to write all this. What about using classnames? Let’s see~

const { useState } = React

const App = () => {  
  const [hide, setHide] = useState(false)

  // classNames will return 'other-class hide' if hide is true  
  const textClassName = classNames('other-class', {  
    hide,  
    // add more e.g isWhite: true,  
  })  
    
  const handleToggle = () => {  
    setHide(prevHide => !prevHide)    
  }  
    
  return (  
    <div>  
      <p className={textClassName}>Text to see</p>  
      <button onClick={handleToggle}>Toggle</button>  
    </div>  
  )  
}

ReactDOM.render(<App />, document.getElementById("root"));

As you can see it is more clean and easy to control the class name return conditionally. Have a try!

prop-types

prop types checking feature it was built-in into React, but since React v15.5 it has moved into a different package. Therefore, you have to install it manually. prop-types does two things, one is set prop’s type and second which is set a default value. For some reason, your custom component needs to set default value and type checking, I think it is a good way to set your default props and default value and it is very easy to understand, check this out!

immer

immer is use to create immutable state which mean to avoid mutate the state directly. But you might think … Why? why we need avoiding to mutate the state directly? Because … Javascript Object & Array are pass by reference. Ok… now what is pass by reference? Pass by reference is

the variable value which is object/array will always refering to the same source not matter how many of variable you assign.

Let’s see this example

Browser Console

As you can see at the very begining, I created a new Object a which store { name: 'Edwin' }and next I assign variable a to b so b also have the same set of object a have. Then console log b out and the result is expected { name: 'Edwin' }

Now I modify variable a object name to Someoneelse and then console log b out again. Gotcha!!! why **b** name is changed? I only modified variable **a** name only. This is because b variable are refering the a source instead of create/clone a new set of Object.

Can you imagine if you didnt manage to avoid this behave in your React project? Your state is going to MESS OUT and unpredictable and uncontrollable. Of course, there must be a solution to help like we always see in the documentation by using the ES6 dot spread syntax when updating the state in reducer.

So now you might ask “ES6 dot spread syntax will do the job what for immer do?”. Although it will do but at some point you will find out dificulty and hard to maintence when dealing with nested object or array.

Let’s see the following reducer which contain a dispatch type UPDATE_HOBBY to update by adding new hobby.

const INITIAL_STATE = {  
  name: 'Edwin',  
  hobbies: ['swiming', 'coding']  
}

export default (state = INITIAL_STATE, action) => {
  switch(action.type) {
    case 'UPDATE_HOBBY':  
      return {  
        ...state,  
        hobbies: [  
          ...state.hobbies,  
          action.hobby  
        ]
      }
    default:  
      return state
  }
}

you will see 2 lines of dot spread is using, because the dot spread only merge the first level of property not in depth. How about using immer? let’s see

import { produce } from 'immer'

const INITIAL_STATE = {  
  name: 'Edwin',  
  hobbies: ['swiming', 'coding']  
}

export default (state = INITIAL_STATE, action) => {
  switch(action.type) {
    case 'UPDATE_HOBBY':  
      return produce(state, draftState => {  
        draftState.hobbies.push(action.hobby)

        // you can do anything here without effecting original state  
        // like draftState.name = 'Someoneelse'  
      })
    }
    default:  
      return state
  }
}

immer produce actually takes your state to create another new draft state (That is the magic happen). immer allow you to mutate the object value in Javascript native way without worry about the outside world! Plus, no learning curve!! because is only produce you have to know and updating the state it just a javascript way to go.

I hope this will answer you. It’s totally ok if you still couldn’t get it, because there is someone who explain it better than me. Check this video out!!

formik

If you work on form builder before, you will know that is a pain!! By getting all the input value submitted, set state for each input value when onchange/onblur, also by knowing which input is touched, validation, display errors message in form input UI and etc.

All these is pain and tears. It requires amount of effort and time to setup (depends on the form input) hopefully formik comes for help! Feel free to check it out the demo.

yup

yup is an object schema validator. In general, you defined a schema for your object and pass the object to validate and it will return the validation errors according to your schema. It can be useful to validate POST body object before sending to the server. It also works really well with formik validationSchema . Give a try https://runkit.com/jquense/yup#

Hope this article find you well, feel free to comment and share your favourite package too~ :)