{"id":2305,"date":"2022-01-26T10:00:10","date_gmt":"2022-01-26T10:00:10","guid":{"rendered":"https:\/\/lvboard.infostore.in.ua\/?p=2305"},"modified":"2022-01-26T10:00:10","modified_gmt":"2022-01-26T10:00:10","slug":"an-overview-of-state-management-solutions-for-react-and-nextjs","status":"publish","type":"post","link":"https:\/\/lvboard.infostore.in.ua\/?p=2305","title":{"rendered":"An overview of State Management solutions for React and NextJS"},"content":{"rendered":"\n<p>React.js has undergone massive developments in recent times, resulting in various state management libraries. <\/p>\n\n\n\n<!--more-->\n\n\n\n<p>With React projects making use of an enormous code base, there is a need to centralize and maintain code and handle data flow across the application. State Management manages code and data maintenance, improving code quality and data sharing between application components. We will discuss the best choices for state management in this article<strong>.<\/strong><\/p>\n\n\n\n<h2 id=\"goals\"><strong>Goals<\/strong><\/h2>\n\n\n\n<p>In this article, we will discuss the terms state and state management. We will also talk about different state management methods; using Redux, Recoil, and Context API.<\/p>\n\n\n\n<h2 id=\"what-is-state-and-state-management\"><strong>What is State and State Management<\/strong><\/h2>\n\n\n\n<p>State in JavaScript applications simply refers to all data generated through user actions. It is a plain JavaScript object that holds information used by React to render components in which its content is dynamic depending on the resultant action of users. React applications, whether functional or class components can have stated. In react applications, data can be passed between components through a method called &#8220;Prop-drilling&#8221;. This is when data is passed continuously from parents to descendants. But as the application gets larger, the need for a global state to hold and share states arises.<br>In large applications such as e-commerce sites, when users interact with a certain component changes are effected into components in the application. For instance:<\/p>\n\n\n\n<ul><li>Adding a shopping item to a cart requires the resulting data to be passed from the shopping component to the cart component.<\/li><li>Add purchased product to user purchase history<\/li><li>Checkout of items in the cart<\/li><li>In complex apps, these changes can be difficult to track, therefore the need for a structure to handle data flow and manage communication between our app\u2019s components. State management is a definite structure for managing communication and sharing of states in our application.<\/li><li>State management libraries provide us with tools to create and manage updates of these structures. Over the years, different state management libraries have been developed. Knowing what state management libraries to use is crucial to the development of an application. In this tutorial, we will be looking at some state management libraries and how they can be used.<\/li><\/ul>\n\n\n\n<h2 id=\"hooks\"><strong>Hooks<\/strong><\/h2>\n\n\n\n<p>There are many methods of managing state in React applications. You can opt for class-based state management, React Hooks or third-party libraries like <a href=\"https:\/\/redux.js.org\/introduction\/getting-started\" target=\"_blank\" rel=\"noreferrer noopener\">Redux<\/a> or Recoil. In this section, we&#8217;ll talk about how we can manage state using Hooks which is <a href=\"https:\/\/reactjs.org\/docs\/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both\" target=\"_blank\" rel=\"noreferrer noopener\">encouraged<\/a> by the React Docs.<\/p>\n\n\n\n<p>According to the <a href=\"https:\/\/reactjs.org\/docs\/hooks-overview.html#but-what-is-a-hook\" target=\"_blank\" rel=\"noreferrer noopener\">React Docs<\/a>, Hooks are basically functions that let you access state and other React features without using a class component. So no single object holds all the state of the component. This allows you to split state into chunks that can be independently updated.<\/p>\n\n\n\n<p>In this section, we&#8217;ll be looking at a few of the most important Hooks used to manage state. We&#8217;ll talk about setting state using the useState and useReducer Hooks.<\/p>\n\n\n\n<p><strong>The useState Hook<\/strong><br>The useState Hook is useful for setting and updating state, similar to this.state in a a class component. With useState you can set the value without referencing the current state.<\/p>\n\n\n\n<p><code><strong>const<\/strong> [state, setState] = useState(initialState);<\/code><\/p>\n\n\n\n<p><code>useState<\/code> is a function that takes in the initial state (initialState in the code above) as an argument. It returns an array of two items which we obtain and assign their values to any variable name we choose using destructuring.<br>The first item ( state ) from the returned array is a variable containing the state which you can use in your component.<br>The second item from the array is a function ( <code>setState<\/code> ) that will update the state.<\/p>\n\n\n\n<p>Let&#8217;s have a look at this Hook in action with this example Movies component.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>import React, { useState } from \"react\";\n\n\/\/ array of movie objects\nconst movies = [\n  {\n    title: \"Black Widow\",\n    price: \"12.00\",\n    rating: \"4.0\"\n  },\n  {\n    title: \"Justice Leage - Snyder Cut\",\n    price: \"10.00\",\n    rating: \"4.9\"\n  }\n];\n\nexport default function Movies() {\n  \/\/ create state variables with initial values\n  const [bookedMovies, setBookedMovies] = useState([]);\n  const [totalPrice, setTotalPrice] = useState(0);\n\n  \/\/ functions to set the state\n  const add = () =&gt; {\n    \/\/ set state for bookedMovies\n    setBookedMovies([movies[0]]);\n    \/\/ set state for totalPrice\n    setTotalPrice(movies[0].price);\n  };\n\n  \/\/ reset state values\n  const remove = () =&gt; {\n    \/\/ reset values\n    setBookedMovies([]);\n    setTotalPrice(0);\n  };\n\n  return (\n    &lt;div&gt;\n      &lt;header&gt;\n        &lt;p&gt; No. of movies: {bookedMovies.length} &lt;\/p&gt;\n        &lt;p&gt; Total price: ${totalPrice} &lt;\/p&gt;\n      &lt;\/header&gt;\n\n      &lt;ul className=\"movies\"&gt;\n        {movies.map((movie) =&gt; {\n          return (\n            &lt;li className=\"movie\" key={movie.name}&gt;\n              &lt;header&gt;\n                &lt;h3&gt; {movie.title} &lt;\/h3&gt;\n                &lt;p&gt; ${movie.price} &lt;\/p&gt;\n              &lt;\/header&gt;\n\n              &lt;button onClick={add}&gt; Add &lt;\/button&gt;\n              &lt;button onClick={remove}&gt; Remove &lt;\/button&gt;\n            &lt;\/li&gt;\n          );\n        })}\n      &lt;\/ul&gt;\n    &lt;\/div&gt;\n  );\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/ BeforeUnloadEvent(()=&gt;{\n\/\/   alert('before now')\n\/\/ })\n<\/code><\/pre>\n\n\n\n<p>Here, we imported the <code>useState<\/code> Hook from React. Then we initialized two independent states of data: <code>bookedMovies<\/code> and <code>totalPrice<\/code>.<\/p>\n\n\n\n<p>This is a huge advantage of <code>useState<\/code> hooks over class-based state management, which provides only a single state object. With Hooks, we can have multiple and independent state objects by just calling the <code>useState<\/code> function, provide an initial state or value and assign the items of the array to new variables.<\/p>\n\n\n\n<p>Let&#8217;s see how we can set the value of our state. Here, we&#8217;ll create a function that will allow users to update our state with some predefined data. First we&#8217;ll create a function that will add a new movie to our <code>bookedMovies<\/code> array and set the price.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>...\n\nexport default function Movies() {\n  \/\/ create state variables with initial values\n  const [bookedMovies, setBookedMovies] = useState([]);\n  const [totalPrice, setTotalPrice] = useState(0);\n\n  \/\/ functions to set the state\n  const add = () =&gt; {\n    \/\/ set state for bookedMovies\n    setBookedMovies([movies[0]]);\n    \/\/ set state for totalPrice\n    setTotalPrice(movies[0].price);\n  };\n\n  \/\/ reset state values\n  const remove = () =&gt; {\n    \/\/ reset values\n    setBookedMovies([]);\n    setTotalPrice(0);\n  };\n\n  return (\n    &lt;div&gt;\n      &lt;header&gt;\n        &lt;p&gt; No. of movies: {bookedMovies.length} &lt;\/p&gt;\n        &lt;p&gt; Total price: ${totalPrice} &lt;\/p&gt;\n      &lt;\/header&gt;\n\n      &lt;ul className=\"movies\"&gt;\n        {movies.map((movie) =&gt; {\n          return (\n            &lt;li className=\"movie\" key={movie.name}&gt;\n              &lt;header&gt;\n                &lt;h3&gt; {movie.title} &lt;\/h3&gt;\n                &lt;p&gt; ${movie.price} &lt;\/p&gt;\n              &lt;\/header&gt;\n\n              &lt;button onClick={add}&gt; Add &lt;\/button&gt;\n              &lt;button onClick={remove}&gt; Remove &lt;\/button&gt;\n            &lt;\/li&gt;\n          );\n        })}\n      &lt;\/ul&gt;\n    &lt;\/div&gt;\n  );\n}<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/codesandbox.io\/s\/vibrant-waterfall-7xyys?file=\/src\/App.js\" target=\"_blank\" rel=\"noreferrer noopener\">Edit on CodeSandbox<\/a><\/p>\n\n\n\n<p>In the code above, we created two functions, <code>add()<\/code> and remove. The <code>add()<\/code> function uses the function <code>setBookedMovies<\/code> to set the value of <code>bookedMovies<\/code> and `setTotalPrice` to set the value of <code>totalPrice.<\/code><\/p>\n\n\n\n<p>We&#8217;re calling this <code>add()<\/code> function using the <code>onClick<\/code> event listener on the Add button.<br>Once the button is clicked, <code>bookedMovies<\/code> is assigned the value of the first movie in the movies list ( &#8220;Black Widow&#8221; ) and <code>totalPrice<\/code> now contains the price of the first movie ( 12.00 ).<br>On the other hand, the <code>remove()<\/code> function sets <code>bookedMovies<\/code> and <code>totalPrice<\/code> to an empty array and 0 respectively.<\/p>\n\n\n\n<p>Great! We&#8217;ve seen how we can set and update state data with <code>useState.<\/code> But we&#8217;re using static, hard-coded values. In real-world applications, you may need to use the previous state to set the new state instead of overwriting it. Let&#8217;s see how we can update the state using the current state with the <code>useReducer<\/code> hook.<\/p>\n\n\n\n<p><strong>The useReducer Hook<\/strong><br>So far we&#8217;ve been updating our state and overwriting the previous state with static values. However, in a real application, you&#8217;ll want to be able to update the booked movies with the previous items in place.<\/p>\n\n\n\n<p>With <code>useReducer<\/code> we&#8217;ll be able to update the state based on the previous state. This Hook is designed to update the state based on the current state like the Array Reduce method.<\/p>\n\n\n\n<p>First, we&#8217;ll create a <code>bookedMoviesReducer<\/code> function which takes in two arguments, state, and <code>action.state<\/code> is the current state and action is an object containing two properties, the movie object and the type of action to be performed on the state &#8211; &#8220;add&#8221; or &#8220;remove&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>...\n\nfunction bookedMoviesReducer(state, action) {\n\n    \/\/ get the movie object and the type of action by destructuring\n    const { movie, type } = action\n\n    \/\/ if \"add\"\n    \/\/ return an array of the previous state and the movie object\n    if (type === \"add\") return [...state, movie]\n\n    \/\/ if \"remove\"\n    \/\/ remove the movie object in the previous state\n    \/\/ that matches the title of the current movie object\n    if (type === \"remove\") {\n        const movieIndex = state.findIndex( x =&gt; x.title === movie.title)\n\n        \/\/ if no match, return the previous state\n        if(movieIndex &lt; 0 ) return state \n\n        \/\/ avoid mutating the original state, create a copy\n        const stateUpdate = [...state]\n\n        \/\/ then splice it out from the array\n        stateUpdate.splice(movieIndex, 1)\n        return stateUpdate\n    }\n    return state\n}\n\n...\n\nexport default function Movie(){\n    ...\n}<\/code><\/pre>\n\n\n\n<p>Then, we have a <code>totalPriceReducer<\/code> function which takes the same arguments as the <code>bookedMoviesReducer<\/code> but just adds and subtracts the value of the previous state to and from the new one respectively.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>... \n\nfunction totalPriceReducer(state, action) {\n    const{ price, type } = action\n    if (type === \"add\") return state + price\n\n    \/\/ return the value when the type of action was not \"add\"\n    \/\/ subract the new movie price from the previous state\n    return (state - price) &lt; 0 ? 0 : ( state - price )\n}\n\n...\n\nexport default function Movie(){\n    ...\n}<\/code><\/pre>\n\n\n\n<p>Note the ternary operator in the return statement above. This resets the calculation to 0 if state &#8211; price is ever lesser than 0 (negative).<\/p>\n\n\n\n<p>Now that we have our refactored functions, let&#8217;s use them in <code>useReducer<\/code><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>import React, { useReducer } from 'react';\n\n...\n\nexport default function Movies() {\n  \/\/ replace useState with useReducer and pass two arguments\n  \/\/ the first argument is the reducer function\n  \/\/ the second function is the initialState\n  const [bookedMovies, setBookedMovies] = useReducer(bookedMoviesReducer, []);\n  const [totalPrice, setTotalPrice] = useReducer(totalPriceReducer, 0);\n\n  \/\/ function to add items and price\n  const add = (movie) =&gt; {\n    \/\/ pass an object containing the movie and type of action, \"add\"\n    setBookedMovies({ movie, type: \"add\" });\n    setTotalPrice({ price: movie.price, type: \"add\" });\n  };\n\n  \/\/ function to remove items and price\n  const remove = (movie) =&gt; {\n    setBookedMovies({ movie, type: \"remove\" });\n    setTotalPrice({ price: movie.price, type: \"remove\" });\n  };\n\n  return (\n    ...\n  )\n}\n...<\/code><\/pre>\n\n\n\n<p>Now that we&#8217;ve edited our <code>add()<\/code> and <code>remove()<\/code> function to take a movie argument, we can pass in the movie as the argument in our <code>onClick<\/code> listener in our template.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>...\n\n{movies.map((movie) =&gt; {\n  return (\n    &lt;li className=\"movie\" key={movie.name}&gt;\n      &lt;header&gt;\n        &lt;h3&gt; {movie.title} &lt;\/h3&gt;\n        &lt;p&gt; ${movie.price} &lt;\/p&gt;\n      &lt;\/header&gt;\n\n      &lt;button onClick={() =&gt; add(movie)}&gt; Add &lt;\/button&gt;\n      &lt;button onClick={() =&gt; remove(movie)}&gt; Remove &lt;\/button&gt;\n    &lt;\/li&gt;\n  );\n})}\n...<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/codesandbox.io\/s\/angry-beaver-tjgqy?file=\/src\/App.js\" target=\"_blank\" rel=\"noreferrer noopener\">Edit on CodeSandbox<\/a><\/p>\n\n\n\n<p>Now if we click on the Add button, it runs the <code>add()<\/code> function which takes movie as an argument which is in turn passed into the setBookedMovies and <code>setTotalPrice<\/code> functions. Each of these functions are returned from their respective <code>useReducer<\/code> functions.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>const [ bookedMovies, setBookedMovies ] = useReducer(bookedMoviesReducer, []);\nconst [ totalPrice, setTotalPrice ] = useReducer(totalPriceReducer, 0);<\/code><\/pre>\n\n\n\n<p>Each function takes an object as an argument.<br>For <code>setBookedMovies<\/code>, it takes this object &#8211; <code>{movie, type: \"add\"}<\/code> as an argument, while, <code>setTotalPrice<\/code> takes this object &#8211; <code>{price: movie.price, type: \"add\"}<\/code> as an argument.<\/p>\n\n\n\n<p>These objects are then passed into their respective reducer functions to update the state. <code>setBookedMovies<\/code> for example passes its object into <code>bookedMoviesReducer<\/code>.<\/p>\n\n\n\n<p>This reducer function adds this new data to the previous state without overwriting it.<br>You can check out the CodeSandbox above to see this in action.<br>Next, we&#8217;ll see how we can manage state across multiple components using Hooks, Props, and the Context API.<\/p>\n\n\n\n<h2 id=\"context-api\"><strong>Context API<\/strong><\/h2>\n\n\n\n<p>React <a href=\"https:\/\/reactjs.org\/docs\/context.html\" target=\"_blank\" rel=\"noreferrer noopener\">Context API<\/a> was an experimental feature of React that became available to use for production in version <a href=\"https:\/\/reactjs.org\/blog\/2018\/03\/29\/react-v-16-3.html\" target=\"_blank\" rel=\"noreferrer noopener\">16.3.0<\/a> of React.<\/p>\n\n\n\n<p>According to the docs, Context provides a way to pass data through and between components in your app&#8217;s component tree without having to manually pass props down through multiple component levels.<\/p>\n\n\n\n<p>This manual passing of props is often referred to as <strong>prop drilling<\/strong>.<br>With Context, you can set up a &#8220;global&#8221; state for a tree of React components. This state can now be accessible from any component without having to pass it through intermediate components.<\/p>\n\n\n\n<p>To illustrate how we can share state between components using Context API, we&#8217;ll break the app in the example above into two sub-components:<\/p>\n\n\n\n<ul><li><code>BookedMovies<\/code> &#8211; This would contain the total number of booked movies and the total price<\/li><li><code>Movies<\/code> &#8211; This renders a list of all available movies, their details, and then <strong>add<\/strong> and <strong>remove<\/strong> buttons for adding and removing the movie from the booked list.<\/li><\/ul>\n\n\n\n<p>Currently, all our pieces of state, the movies including bookedMovies and totalPrice which we set using Hooks are all in one component &#8211; App.js.<br>For our state to be accessible to our child components, we can pass it down the data using props.<br>This implies that we have to <strong>lift the state up<\/strong> to the topmost component of our component tree and pass it down to the component that needs to access the state. Now, this can be two or more levels down the component tree which takes us back to prop drilling.<\/p>\n\n\n\n<p>Instead of doing all that, we can initialize Context and set up a &#8220;global&#8221; state that can be accessed from any component on the tree.<\/p>\n\n\n\n<p><strong>Initialize Context<\/strong><br>To initialize <a href=\"https:\/\/reactjs.org\/docs\/context.html#reactcreatecontext\" target=\"_blank\" rel=\"noreferrer noopener\">context<\/a>, we can create a new file MoviesContext.js specifically for our Context, import createContext, and create our Context.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>import React, {useReducer, createContext} from 'react';export const MovieContext =  createContext();<\/code><\/pre>\n\n\n\n<p><strong>Create Context Provider<\/strong><br>Now that we&#8217;ve initialized Context, we can create a Context Provider. According to the docs, every Context object comes with a Provider component that allows components wrapped within it to subscribe to context changes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>import React, { useState, useReducer, createContext } from \"react\";\n\nconst moviesList = [\n ...\n];\n\nfunction bookedMoviesReducer(state, action) {\n  ...\n};\n\nexport const MovieContext = createContext();\n\nexport const MovieProvider = (props) =&gt; {\n  const [movies, setMovies] = useState(moviesList);\n  const [bookedMovies, setBookedMovies] = useReducer(bookedMoviesReducer, []);\n\n  return &lt;MovieContext.Provider&gt;{props.children}&lt;\/MovieContext.Provider&gt;;\n};<\/code><\/pre>\n\n\n\n<p>Here, we&#8217;ve moved all our state and reducer functions into our Context file MoviesContext.js. Then in our MovieProvider function, we initialize the state using useState and useReducer Hooks.<\/p>\n\n\n\n<p>Finally, we&#8217;re returning the Provider component <code>&lt;MovieContext.Provider&gt;.<\/code> props.children will allow us to render the components that will be nested within the provider.<br>Here&#8217;s our refactored App.js file with imported components and Context.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/ .\/App.js\n\nimport React from \"react\";\nimport Movies from \".\/components\/Movies\";\nimport BookedMovies from \".\/components\/BookedMovies\";\nimport { MovieProvider } from \".\/moviesContext\";\n\nexport default function App() {\n  return (\n    &lt;MovieProvider&gt;\n      &lt;main&gt;\n        &lt;Movies \/&gt;\n        &lt;BookedMovies \/&gt;\n      &lt;\/main&gt;\n    &lt;\/MovieProvider&gt;\n  );\n}<\/code><\/pre>\n\n\n\n<p>Great. We&#8217;ve managed to create a provider and wrap our components with the provider in our app. We currently don&#8217;t have access to any of our state from the Context. Let&#8217;s see how we can consume or use the state.<\/p>\n\n\n\n<p><strong>Consuming our state<\/strong><br>The Provider component accepts a value <a href=\"https:\/\/reactjs.org\/docs\/context.html#contextprovider\" target=\"_blank\" rel=\"noreferrer noopener\">prop<\/a> that can be accessed by components that are descendants of the Provider. We have to pass all our state into our app in our Context file MoviesContext.js<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/ .\/MoviesContext.js\n...\n  return (\n    &lt;MovieContext.Provider\n      value={{\n        movies,\n        setMovies,\n        bookedMovies,\n        setBookedMovies,\n      }}\n    &gt;\n      {props.children}\n    &lt;\/MovieContext.Provider&gt;\n  );\n...<\/code><\/pre>\n\n\n\n<p>To subscribe to these pieces of state in our components, we have to import MovieContext and consume it with the useContext Hook. Here&#8217;s how we can do that in our Movies component.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/ .\/components\/Movies.js\n\n\/\/ import the useContext Hook\nimport React, { useContext } from \"react\";\n\/\/ import the Context\nimport { MovieContext } from \"..\/moviesContext\";\n\nexport default function Movies() {\n  const { movies, setBookedMovies } = useContext(MovieContext);\n  \/\/ function to add items and price\n  const add = (movie) =&gt; {\n    \/\/ pass an object containing the movie and type of action, \"add\"\n    setBookedMovies({ movie, type: \"add\" });\n  };\n\n  \/\/ function to remove items and price\n  const remove = (movie) =&gt; {\n    setBookedMovies({ movie, type: \"remove\" });\n  };\n\n  return (\n    &lt;ul className=\"movies\"&gt;\n      {movies.map((movie) =&gt; {\n        return (\n          &lt;li className=\"movie\" key={movie.name}&gt;\n            &lt;header&gt;\n              &lt;h3&gt; {movie.title} &lt;\/h3&gt;\n              &lt;p&gt; ${movie.price} &lt;\/p&gt;\n            &lt;\/header&gt;\n\n            &lt;button onClick={() =&gt; add(movie)}&gt; Add &lt;\/button&gt;\n            &lt;button onClick={() =&gt; remove(movie)}&gt; Remove &lt;\/button&gt;\n          &lt;\/li&gt;\n        );\n      })}\n    &lt;\/ul&gt;\n  );\n}<\/code><\/pre>\n\n\n\n<p>Now we can access all our state from this component. We can also do the same thing for our BookedMovies component.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/ .\/components\/BookedMovies.js\n\nimport React, { useContext } from \"react\";\nimport { MovieContext } from \"..\/moviesContext\";\n\nfunction BookedMovies() {\n  const {bookedMovies} = useContext(MovieContext);\n\n  const getTotalPrice = (bookedMovies) =&gt; {\n    const totalPrice = bookedMovies.reduce((totalCost, item) =&gt; totalCost + item.price, 0);\n    return totalPrice\n  }\n\n  return (\n    &lt;header&gt;\n      &lt;p&gt; No. of movies: {bookedMovies.length} &lt;\/p&gt;\n      &lt;p&gt; Total price: ${getTotalPrice(bookedMovies)} &lt;\/p&gt;\n    &lt;\/header&gt;\n  );\n}\n\nexport default BookedMovies;<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/codesandbox.io\/s\/determined-star-mhess\" target=\"_blank\" rel=\"noreferrer noopener\">Edit on CodeSandbox<\/a><\/p>\n\n\n\n<p>There we go. We&#8217;ve managed to subscribe to <code>bookedMovies<\/code> state from our Context in this component. Also, we&#8217;ve refactored the total price functionality and created a new function <code>getTotalPrice<\/code> that will get the price from each movie on the <code>bookedMovie<\/code> array and total it.<\/p>\n\n\n\n<p>That&#8217;s how we can manage state using the Context API and Hooks.<br>In the next sections, we&#8217;ll see how we can manage state using other popular libraries like Redux and Recoil.<\/p>\n\n\n\n<h2 id=\"redux\"><strong>Redux<\/strong><\/h2>\n\n\n\n<p><strong>What is Redux?<\/strong><br><a href=\"https:\/\/redux.js.org\/introduction\/getting-started\" target=\"_blank\" rel=\"noreferrer noopener\">Redux<\/a> as the doc implies is a container for Javascript apps. It allows us to manage our app state, track and manage changes as the app progresses. Redux allows React components to read data from a Redux store and dispatch actions to the store to update this data. Here is a diagrammatic representation of how Redux works:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/lh3.googleusercontent.com\/Vjlw1JurwenOzgPybaiXmxPbEVvd12_v2a23axxoqbFiQaT5p1fpjssJf0oZORXzxwOOSloV8QT_ZivBb5F4XK7-Jv6UCX3AsGQn9O5LlmUaMCRRStNJZYh45tQrjgVQ8lUNLwAS\" alt=\"Content image\"\/><\/figure>\n\n\n\n<p>The UI is updated based on the changes made to the state stored in the store thereby making it easier to continuously update as changes are made.<br>Redux provides a central store where our state resides. Each component in the application can then access the stored data without having to send it from one component to another.<\/p>\n\n\n\n<h2 id=\"when-should-we-use-redux\"><strong>When should we use Redux?<\/strong><\/h2>\n\n\n\n<p>You can use Redux in your application when:<\/p>\n\n\n\n<ul><li>There are large amounts of states in the app that undergo frequent updates. It solves the problem of prop drilling between components and makes it easier to handle continuous mutations of states.<\/li><li>When a complex algorithm is required to handle updating of the app\u2019s states.<\/li><li>When a reasonable amount of data changes overtime. If the application has data that is constantly being updated, Redux can be used to manage this data and create a structure for it.<\/li><li>When state management is shared. Redux is suitable for cases where the application is shared over a codebase with different developers working on the same application.<\/li><\/ul>\n\n\n\n<h2 id=\"how-does-redux-work\"><strong>How Does Redux Work?<\/strong><\/h2>\n\n\n\n<p>Redux is made up of three primary components: Redux Store, Action, and Reducer.<\/p>\n\n\n\n<p><strong>Redux Store: This<\/strong> is the brain of our state management structure. It manages the state and dispatches Action on managing the state of our application.<\/p>\n\n\n\n<p><strong>Action<\/strong>: refer to instructions sent that can be interpreted by Reducers. It stores information regarding the users\u2019 actions. The action contains a type and a payload. The type is simply a string with the action name while the payload contains the actual data passed by the action.<\/p>\n\n\n\n<p><strong>Reducers:<\/strong> These are functions that read the instructions sent by the Action and update the store via the state according to the received instructions. They specify how the application&#8217;s state will change in response to the actions sent to the store.<br>Redux promotes good architectural structure in React apps along with UI management and optimizes performance for easy re-rendering of components when needed.<br>Redux core benefits include:<\/p>\n\n\n\n<ul><li>Flexibility: Redux is simple to learn and implement. It does not require deep knowledge to make use of.<\/li><li>Maintainable: Redux is straightforward and easy to maintain and control operations on the stored state.<\/li><li>Scalability: Since Redux deals with a central store that contains the state that is shared by components, it makes it suitable for handling states when building complex applications.<\/li><li>Redux supports server-side rendering: The current state of an app can be sent to the server with the response to mutate the state.<\/li><li>Easy to debug: Since Redux is made up of three core parts: the Store, Actions, and Reducers. By logging the values of these parts it is easy to trace and fix errors if any occur.<\/li><\/ul>\n\n\n\n<p>We will now look at how to set up and use Redux in an app using a counter application as a case study.<\/p>\n\n\n\n<h2 id=\"redux-setup\"><strong>Redux Setup<\/strong><\/h2>\n\n\n\n<p>To set up Redux for use in our application, we will first need to install the package via CLI<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>npm i redux react-redux<\/code><\/pre>\n\n\n\n<p>Once this is installed, we can create our action and reducer file; action.js, and reduce.js.<br>In the reduce.js file, we have:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>const reduce = (state = 0, action) =&gt; {\n  switch (action.type) {\n    case \"reset value\":\n      return (state = 0);\n    case \"increase value\":\n      return state + 1;\n    case \"decrese value\":\n      return state - 1;\n    default:\n      return state;\n  }\n};\nexport default reduce;<\/code><\/pre>\n\n\n\n<p>Above, we created our reducer file which takes state as value &#8220;0&#8221; then based on the value of action.type which is the name of the action makes changes to the value of the state. We have set up a conditional block to make different changes based on the type of action dispatched to the reducer. As defined, if the action type is &#8220;reset value&#8221;, state will be set to 0, if the action type is &#8220;increase value&#8221;, the value of state will be increased by one and vice-versa.<\/p>\n\n\n\n<h2 id=\"creating-a-central-store\"><strong>Creating a Central Store<\/strong><\/h2>\n\n\n\n<p>To create the store, we will need to create a new file and import createstore from redux:<\/p>\n\n\n\n<p><code>import { createStore } from \"redux\";<\/code><\/p>\n\n\n\n<p>We also need to import our reducer into the file. After which we will import Provider from Redux. The Provider is responsible for connecting the central state to our application. We will need to wrap the components that will use the Redux state within the provider, preferably in the root.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>import reduce from \".\/reduce\"\nimport { Provider } from \"react-redux\";<\/code><\/pre>\n\n\n\n<p>Then to create the store:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>const store = createStore(\n  reduce,\n);\nReactDOM.render(\n  &lt;React.StrictMode&gt;\n    &lt;Provider store={store}&gt;\n      &lt;App \/&gt;\n    &lt;\/Provider&gt;\n  &lt;\/React.StrictMode&gt;,\n  document.getElementById(\"root\")\n);<\/code><\/pre>\n\n\n\n<p>We will have to define our actions and export them in our <code>action.js<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>export const increment = () =&gt; {\n  return {\n    type: \"increment value\",\n  };\n};\n\nexport const decrement = () =&gt; {\n  return {\n    type: \"decrement value\",\n  };\n};\n\nexport const reset = () =&gt; {\n  return {\n    type: \"reset value\",\n  };\n};<\/code><\/pre>\n\n\n\n<h2 id=\"dispatch-actions\"><strong>Dispatch Actions<\/strong><\/h2>\n\n\n\n<p>To dispatch the actions increment value, reset value and decrement value we need to import the actions and use the useDispatch hook provided by react-redux to dispatch our actions.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>import { useDispatch } from \"react-redux\";<\/code><\/pre>\n\n\n\n<p>Then, back in our App.js file, we can create buttons with functionalities to perform the actions we defined:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>import { useSelector, useDispatch } from \"react-redux\";\nimport {\n  decrement,\n  increment,\n  reset,\n} from \".\/action\";\n\nfunction App() {\n  const counter = useSelector((state) =&gt; state.counter);\n  const dispatch = useDispatch();\n\n  return (\n    &lt;div className=\"App\"&gt;\n      &lt;p&gt;Counter to demonstrate redux&lt;\/p&gt;\n      &lt;h3&gt;{counter}&lt;\/h3&gt;\n      &lt;button onClick={() =&gt; dispatch(increment())}&gt;Increment&lt;\/button&gt;\n      &lt;button onClick={() =&gt; dispatch(reset())}&gt;Reset&lt;\/button&gt;\n      &lt;button onClick={() =&gt; dispatch(decrement())}&gt;Decrement&lt;\/button&gt;\n    &lt;\/div&gt;\n  );\n}\nexport default App;<\/code><\/pre>\n\n\n\n<p>Here, we have used the useDispatch hook to assign the actions to three different buttons. The value of the counter is based on the current value of the state.<\/p>\n\n\n\n<h2 id=\"recoil\"><strong>Recoil<\/strong><\/h2>\n\n\n\n<p><strong>What is Recoil?<\/strong><br><a href=\"https:\/\/recoiljs.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Recoil<\/a> is a new state management library that is open-sourced by Facebook. Recoil also provides a solution to the problem of Global state in applications. Recoil is made up of two major parts: Atom and Selector. Atom is simply a function that lets us store states. It is a shared-state architecture where different components can connect to it to get values from the stored state. On the other hand, a Selector is similar to Atom except that it allows us to have a derived state. The value of a Selector can be derived from the Atom or another Selector.<\/p>\n\n\n\n<h2 id=\"recoil-setup\"><strong>Recoil Setup<\/strong><\/h2>\n\n\n\n<p>To demonstrate how to use Recoil in an application we will use an example similar to the counter we created in Redux above. To install Recoil, run the following command in your CLI:<\/p>\n\n\n\n<p><code>npm install recoil<\/code><\/p>\n\n\n\n<p>Then we can import it into our app and define our state:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/atom.js\nimport { atom } from \"recoil\";\nconst counter = atom({\n  key: \"counter\",\n  default: 0\n});\n\nexport default counterAtom;<\/code><\/pre>\n\n\n\n<p>Above, the counter is our state. It has a key of &#8220;counter&#8221; and a default value of 0. In Recoil, components that use recoil state need to be wrapped in RecoilRoot. We will add this to our root component:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/index.js\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { RecoilRoot } from \"recoil\";\nimport App from \".\/App\";\n\nReactDOM.render(\n  &lt;RecoilRoot&gt;\n    &lt;App \/&gt;\n  &lt;\/RecoilRoot&gt;,\n  document.getElementById(\"root\")\n);<\/code><\/pre>\n\n\n\n<p>In Recoil, we can use the <code>useRecoilState()<\/code> hook to read the value of a recoil state. Now we will create buttons with the functionality to mutate the state stored in <code>atom.js<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>\/\/ App.js\nimport React from \"react\";\nimport { useRecoilState } from \"recoil\";\nimport counter from \".\/atom\";\n\nconst App = () =&gt; {\n  const [count, setCount] = useRecoilState(counter);\n\n  return (\n    &lt;div&gt;\n      &lt;div&gt;\n        &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;\/button&gt;\n        &lt;span&gt;{count}&lt;\/span&gt;\n        &lt;button onClick={() =&gt; setCount(count - 1)}&gt;Decrement&lt;\/button&gt;\n        &lt;button onClick={() =&gt; setCount(0)}&gt;Reset&lt;\/button&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  );\n};\n\nexport default App;<\/code><\/pre>\n\n\n\n<p>Here, we read in the value of our state from atom.js using useRecoilState. We set up three buttons to increase the value of our count, decrement it and reset it.<\/p>\n\n\n\n<h2 id=\"benefits-of-using-recoil\"><strong>Benefits of Using Recoil<\/strong><\/h2>\n\n\n\n<ul><li>Recoil is a simple way to implement state management. It can be incorporated in applications with simple architectures. Apart from Atom and Selector, there isn&#8217;t much to it, making it easier to understand.<\/li><li>It has a React-like approach as its application is similar to the useState React-hook thereby making it simpler to work within React applications.<\/li><\/ul>\n\n\n\n<h2 id=\"conclusion\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>So far we&#8217;ve seen how we can manage state in our React applications using various methods and libraries.<br>Ranging from Hooks and Context API for small to medium projects and Redux and Recoil for medium to large projects.<br>Still, there are a ton of state libraries to choose from in the React ecosystem and beyond. Most of them are designed and developed around a certain concept and towards a particular use case.<\/p>\n\n\n\n<p>Let&#8217;s highlight some of these state management libraries:<\/p>\n\n\n\n<ul><li><a href=\"https:\/\/xstate.js.org\/docs\/\" target=\"_blank\" rel=\"noreferrer noopener\">XState<\/a> &#8211; Which is a library built on a concept called <a href=\"https:\/\/xstate.js.org\/docs\/about\/concepts.html#finite-state-machines\" target=\"_blank\" rel=\"noreferrer noopener\">state machines<\/a>. State machines allow you to set a run or perform a specific action for a specific or defined state. A very simple example of a state machine can be seen in a switch case statement<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;&gt;<code>switch (state) {\n  case state === 'light':\n  \/\/ enable light  theme\n  break;\n  case state === 'dark':\n  \/\/ enable light theme\n  break;\n  default:\n  \/\/ handle error\n}<\/code><\/pre>\n\n\n\n<ul><li>You can learn more about XState and state machines from this <a href=\"https:\/\/dev.to\/skona27\/future-of-state-management-in-react-with-xstate-kg4\" target=\"_blank\" rel=\"noreferrer noopener\">article<\/a>, <a href=\"https:\/\/xstate.js.org\/docs\/\" target=\"_blank\" rel=\"noreferrer noopener\">the docs<\/a>, or <a href=\"https:\/\/egghead.io\/courses\/introduction-to-state-machines-using-xstate\" target=\"_blank\" rel=\"noreferrer noopener\">watching this course<\/a>.<\/li><li><a href=\"https:\/\/mobx.js.org\/README.html\" target=\"_blank\" rel=\"noreferrer noopener\">Mobx &#8211;<\/a> It is a stage-management library that is unopinionated, not platform-specific, which means it can be used outside react. It follows the transparent application of functional reactive programming (TFRP). Unlike some libraries like Redux, MobX allows multiple Stores. You can get started with <a href=\"https:\/\/mobx.js.org\/installation.html\" target=\"_blank\" rel=\"noreferrer noopener\">MobX<\/a> quite easily as it doesn&#8217;t have a steep learning curve.<\/li><li><a href=\"https:\/\/github.com\/pmndrs\/valtio#readme\" target=\"_blank\" rel=\"noreferrer noopener\">Valtio<\/a> &#8211; A simple lightweight proxy-based state management library that provides a mutation-style API<\/li><li><a href=\"https:\/\/github.com\/pmndrs\/jotai#readme\" target=\"_blank\" rel=\"noreferrer noopener\">Jotai<\/a> &#8211; A Primitive and flexible state management for React which provides a minimalistic API. It supports TypeScript and is optimized for computed values and asynchronous actions to state.<\/li><li><a href=\"https:\/\/github.com\/pmndrs\/zustand\" target=\"_blank\" rel=\"noreferrer noopener\">Zustand<\/a> &#8211; A small, fast, and scalable state-management solution. It&#8217;s specifically focused on module state. This library is based on Hooks and is un-opinionated.<\/li><\/ul>\n\n\n\n<h3 id=\"the-future-of-state-management-in-react\"><strong>The Future of State Management in React<\/strong><\/h3>\n\n\n\n<p>Currently, some of the approaches to state management that we&#8217;ve discussed so far come with some caveats.<br>For example, in large applications, we might have issues with excessive re-rendering with the Hooks + Context API method.<br>This is because when Context value changes, every component subscribes to that Context with useContext will re-render even if it doesn&#8217;t depend on the particular piece of state that was changed.<\/p>\n\n\n\n<p>React has <a href=\"https:\/\/reactjs.org\/docs\/hooks-reference.html#usememo\" target=\"_blank\" rel=\"noreferrer noopener\">useMemo<\/a> which is an available workaround for this re-rendering issue. It&#8217;s a built-in hook that allows you to <a href=\"https:\/\/en.wikipedia.org\/wiki\/Memoization\" target=\"_blank\" rel=\"noreferrer noopener\">memoize<\/a> expensive functions.<\/p>\n\n\n\n<p>In the near future, to fix this issue, the React team has been working on useSelectedContext feature that allows you to subscribe to only a selected part of the Context. You can check out the progress of this feature <a href=\"https:\/\/github.com\/facebook\/react\/pull\/20646\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>Although the new useSelectedContext is an in-house solution to this re-rendering problem, other third-party libraries can be used. <a href=\"https:\/\/github.com\/dai-shi\/use-context-selector\" target=\"_blank\" rel=\"noreferrer noopener\">useContextSelector<\/a> which is being used under the hood by <a href=\"https:\/\/github.com\/pmndrs\/jotai\" target=\"_blank\" rel=\"noreferrer noopener\">Jotai<\/a> and <a href=\"https:\/\/formik.org\/blog\/formik-3-alpha\" target=\"_blank\" rel=\"noreferrer noopener\">Formik 3<\/a>, works similarly.<\/p>\n\n\n\n<p>Moving forward, React will automatically figure out which components to re-render using <a href=\"https:\/\/github.com\/reactjs\/rfcs\/pull\/119#issuecomment-586390430\" target=\"_blank\" rel=\"noreferrer noopener\">auto-memorization<\/a>.<\/p>\n\n\n\n<p>All this in addition to the current and purpose-specific options for state management makes React a solid choice for many organizations in developing their products.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>React.js has undergone massive developments in recent times, resulting in various state management libraries.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[30],"tags":[161,65],"_links":{"self":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2305"}],"collection":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2305"}],"version-history":[{"count":1,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2305\/revisions"}],"predecessor-version":[{"id":2306,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2305\/revisions\/2306"}],"wp:attachment":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}