Hooks in Redux : useSelector and useDispatch
If you have worked with Redux before, then you might agree that despite being a great state management tool, Redux is a little complicated when it comes to the boilerplate code that it needs before you start a project. However, if one wants a simpler and cleaner code with redux then they shall learn about the hooks - useSelector and useDispatch in Redux that serve as an alternative to the existing connect() higher-order function.
What are useDispatch and useSelector Hooks in React.js?
React Hooks are APIs that give the functional components the ability to manage the state of an application, handle the side effects, and write clean and simpler code for an application. They are introduced in React version 16 and are constantly improved over time.
Before the introduction of hooks in react, React redux used the higher order component connect() to connect a component to the redux store and read the values from the redux store each time a state gets updated. The connect() function takes two optional parameters- mapStateToProps, and mapDispatchToProps.
However, with the introduction of hooks, useSelector and useDispatch served as an alternative to the connect() function. The useSelector hook is equivalent to the mapStateToProps and takes an argument that returns the part of the state that the component needs whereas the hook useDispatch acts just like mapDispatchToProps.
What is useSelector?
The useSelector hooks allow you to extract data or the state from the Redux store using a selector function. It is equivalent to the mapStateToProps argument used in the connect() function conceptually. However, there exist some differences between the two such as the selector can return any value as the result and not just an object. Moreover, when an action is performed, the useSelector() hook will compare the results of the previous and current selector values and if they are different then the component is bound to re-render otherwise it stays the same.
However, the main difference between the two is that the mapStateToProps pass down multiple values as props whereas the useSelector will take the current state as the argument and returns a single variable as a result.
The function will be called with the entire redux store state as an argument and runs whenever the functional components render the page. The useSelector() hook will subscribe to the redux store and runs whenever an action is dispatched. You may call the useSelector() any number of times in a single function. However, each call will create an individual subscription to the redux store.
How to Use useSelector Hook in React?
Let us understand the usage of the useSelector hook with the help of a code example in which we will create a counter application with an increment and a decrement button.
For importing redux into your project, type the following command in your terminal.
After successfully installing the two libraries, navigate to the src/ folder of your project and create an actions/ folder. Inside the actions/ folder, make increment.js and decrement.js files.
In the above files, we have created two actions with the type INCREMENT and DECREMENT to tell the reducer what actions to perform.
After this, create a reducers/ folder inside the src/ folder and a counter.js file inside the reducers/ folder.
In the above code, we have made a reducer function that takes the state and action as an argument and updates the state based on the action given by the user.
Now, we will be creating a global store in the index.js file by writing the following code.
For creating a store, we have used the configureStore() method which takes the reducer and a preloadedState as the arguments. We have given the reducer function present in the counter.js file whereas the preloadedState would be the initialState of the counter.
Now, we will make the store global with the help of the following code in the index.js file.
We have wrapped the App component with the Provider from react-redux and given the store created by us previously.
After which simply implement the useSelector hook to get the value from the global store in redux.
In the above code, the value variable will contain the state of the redux store using the useSelector hook.
However, we have not changed the state yet therefore, for now, it will use the value of the initialState only.
What is useDispatch?
The useDispatch is yet another hook in redux which is equivalent to the mapDispatchToProps argument in the connect() higher-order function. It allows you to send or dispatch an action to the redux store by giving the action as an argument to the dispatch variable.
The useDispatch hook will return a reference to the dispatch function from the redux store. You can use it to dispatch the actions whenever needed.
How to Use useDispatch Hook in React?
To understand how to use the useDispatch hook, we will be continuing the same example as discussed for the useSelector hook.
However, as discussed previously, we have made the global store and have implemented the useSelector hook by which the initial state of the component was visible to us. By using the useDispatch hook, we will be able to increment and decrement the state by clicking on the buttons that we have made in the previous example.
Let us see the code for the same. The below code needs to be written in the App.js file.
In the above code, we have created a dispatch variable that implements the useDispatch() hook. After this, we created the functions handleIncre and handleDecre that dispatches the actions increment and decrement that we have created in the actions folder.
Therefore, as soon as the buttons will be clicked, the functions will be triggered and the action will be dispatched to change the state of the component.
Now, let us see another example to understand the usage of the useSelector and useDispatch hooks better. In this example, we will be implementing a log-in and logOut feature using the redux hooks.
Let us begin by installing the redux and the react-redux libraries using the below code.
In this example, we will be having one state to keep track of the loggedIn user.
Create an Actions and Reducers Folder
Firstly, create the actions and a reducers folder inside the src/ folder.
Inside the actions folder, create the userActions.js file with the following code to create the action for the login and logout for a user.
Now, inside the reducer folder, create a currentUser.js file that has a currentUser function that performs the action and returns a new state to the redux store.
Below is the code for the same.
The currentUser() function takes two arguments state and action, the state is set to an empty object as it will be the initial state of the component.
Inside the function, we have changed the state of the component based on the action provided by the user.
Now, let us make the redux store to store the state of the user. For doing so, write the following code in the index.js file.
In the above code, we have wrapped the App component with Provider and given the store as the redux store. Also, we have made the global redux store using the configStore().
Implement useSelector and useDispatch
Now, let us implement the useSelector and useDispatch hooks for updating the state of the component in redux.
Below is the code for the same.
In the above code, we have used the useSelector to get the current state of the component, that is, whether the user is loggedIn or loggedOut.
After which we used the useDispatch hook and store it in a variable dispatch. We have also stored the name of a user and used it to show the login feature.
If the currentUser is already logged in then we provide them with a logout option whereas if the user is logged out then they will be getting a message saying Logged In as user and a logout option.
- The useSelector hook is used to extract the state of a component from the redux store using the selector function.
- The useDispatch hook is used to update the state of the component and return a new state.
- Redux boilerplate code made the library a little tedious but with the introduction of these hooks in redux, the code became even more straightforward and cleaner.
- These hooks are used as an alternative to the connect() higher-order function in redux.
- The useSelector and useDispatch hooks implement logIn/logOut, and increment/decrement functionalities very easily and with a simple code compared to the tedious and large redux code.
- Both these hooks go hand in hand and update the state of an application in very less time.