REACT (https://www.kirupa.com/react/index.htm) BOOK (https://www.amazon.com/exec/obidos/ASIN/0134546318/kirupacom) Using Redux with React by kirupa (https://www.kirupa.com/me/index.htm) | filed under Learning React (https://www.kirupa.com/react/index.htm) Now that you have a better idea of how Redux works (https://www.kirupa.com/react/introduction_to_redux.htm), let's look at the topic we set out to better understand in the first place. Why is Redux so popular in React projects? To help answer this, take a look at the following component hierarchy for some arbitrary app: [Image: ] (https://www.kirupa.com/react/images/react_redux_app_200.png) What this app does isn't very important. The only detail we'll throw in there is that that some of these components are responsible for managing state and transferring some of that state around in the form of props: [Image: ] (https://www.kirupa.com/react/images/react_redux_app_data_200.png) In the ideal setup, this data each component needs will flow neatly down from parent to child: [Image: ] (https://www.kirupa.com/react/images/react_redux_app_dataflow_200.png) Unfortunately, outside of simple scenarios, what we would like to do isn't very realistic. Your typical app does a lot of state generating, processing, and transferring! One component may initiate a state change. Another component somewhere else will want to react to it. The props related to this state change may travel both down the tree (yay!) as well as up the tree (nooo!) to reach whatever component is relying on the data being transferred: [Image: ] (https://www.kirupa.com/react/images/react_redux_app_crazy_200.png) We've been guilty of this quite a few times ourselves as part of communicating something (variable value, function/event handler reference, etc.) from child to parent and beyond. Now, there are a few problems that we need to recognize at this point with data traveling willy nilly through our components: 1. Difficult to maintain. React's stated goal was to avoid spaghetti-like dependencies, but we end up with exactly the thing that we were supposed to be free from when we have data that is flowing around our app. 2. Each time your state changes or a prop is transmitted, all affected components are asked to re-render. To ensure your UI is in-sync with the current state, this behavior is a good thing. As we talked about before, many components are unnecessarily asked to re-render when all they are doing is passing a value from parent to child with no additional input. We looked at ways of minimizing this re-rendering by setting shouldComponentUpdate or relying on PureComponent, but both approaches are a hassle to keep in-sync as your app's data needs evolve. 3. Our component hierarchy mimics the UI and not our data needs. The way we arrange and nest our components is to help separate our UI into smaller and manageable pieces. This is the correct thing to do. Despite the correctness, the components that initiate a state change and the ones that need to react to it are often not in the same parent/child/descendant arrangement (aka subtree). Similar to what we talked about in #ii, this requires our props to travel great distances - often multiple times per change! The solution to our problems is Redux! Now, Redux doesn't solve all of these problems fully, but it gets us really REALLY close. What Redux allows you to do is have all of your application's state live inside its data store instead of being distributed across a bunch of components: [Image: ] (https://www.kirupa.com/react/images/react_redux_app_datastore_200.png) This approach solves several of our problems. If you want to share data from one part of your app with another, you can do that without having to navigate up and down your component hierarchy: [Image: ] (https://www.kirupa.com/react/images/react_redux_initiate_200.png) You can initiate a state change and involve only the impacted components directly. This directness reduces a lot of overhead you would otherwise have to maintain around ensuring your data (and any changes to it) gets to its intended destination without causing unnecessary renders! Pretty cool, right? Now, let's go one level higher. From an architectural point of view, the overview of Redux we saw in the introduction (https://www.kirupa.com/react/introduction_to_redux.htm) still holds: [Image: ] (https://www.kirupa.com/react/images/redux_react_overview_200.png) Besides the store, we still have to work with actions, reducers, and all the other related things that make up the Redux party. The only difference is that our app is built using React, and this difference (and how it plays with Redux) is where we will focus our attention on here. Onwards! Managing React State with Redux The way Redux plugs into your React app is as straightforward as calling a few Redux APIs from your React code. There are just two steps involved: 1. Provide your app a reference to the Redux store 2. Map the action creators, dispatch functions, and state as props to whatever component needs data from our store To see what is involved in bringing these two steps to life, we're going to build a simple Counter app. It will look as follows: [Image: ] (https://www.kirupa.com/react/images/counte_redux.png) Our app will have a plus button and a minus button to increase or decrease a counter value. That's it. There is nothing else that is going on here, but this is just the right level of functionality and complexity to help us get our feet wet with combining React and Redux together. How Redux and React Overlap Given that we just saw what we are going to be building, this is where we would start copying and pasting HTML, CSS, and JavaScript to get our example up and running. We will totally get there in a few moments, but I want to first walk through how this app is structured. Ignoring the data and state management side, we are going to have just two components: [Image: ] (https://www.kirupa.com/react/images/redux_counter_example_200.png) We will have an App component and a Counter component. Now, a counter is not the most complicated of examples to think about. If we had to implement it using plain old state, we would simply create a state object inside Counter and have a variable whose value increased or decreased depending on what button we press. When we throw Redux into the mix, our component arrangement gets a little bizarre. It will look as follows: [Image: ] (https://www.kirupa.com/react/images/redux_counter_hoc_200.png) The items in blue are what we had originally. The items in green are new as part of incorporating Redux into our app. Earlier, we mentioned that adding Redux to our app involved two steps. The green additions mimic those steps closely: 1. The first step of providing access to our Redux store is handled by the Provider component 2. The second step of providing any interested components access to our dispatch and actions is handled by the Connect component Going into a little more detail, the Provider component is the gateway to getting Redux functionality in our React app. It is responsible for storing a reference to our store and ensuring all components in our app have a way of accessing it. The way it is able to do that is by being the top-most component in your component hierarchy. That vaulted position allows it to pass Redux-related wisdom throughout the entire app easily. The Connect component is a bit more interesting. It isn't a full-blown component in the traditional sense. It is known as a Higher Order Component (https://reactjs.org/docs/higher-order-components.html) (or HOC as the cool kids say it). What HOC's do is provide a consistent way to extend the functionality of a pre-existing component by simply wrapping it and injecting their own additional functionality into them. Think of this as the React-friendly way to mimic what the extends keyword does when working with ES6 classes. From looking at our diagram, the end result is that our Counter component, thanks to the Connect HOC, has access to any actions and dispatch calls needed to work with the Redux store without you having to write any special code to access it. The Connect HOC takes care of that. Both the Provider and Connect HOC's create a symbiotic relationship that gives any old React app the ability to easily work with Redux's peculiar (yet totally efficient and awesome) way of managing application state. As we start to build our app, you'll start to see more of how this relationship plays out. Getting Started Now that we have an idea of how our app will be structured and some of the Redux-specific constructs that we'll be using, let's shift gears and start to build our app. To get started, first use create-react app (https://www.kirupa.com/react/setting_up_react_environment.htm) to create an app we will call reduxcounter: create-react-app reduxcounter Once you have created this app, we are going to install the Redux and React Redux dependencies. From inside your Terminal/command line environment, navigate to the reduxcounter folder, and run the following command: npm install redux This will install the Redux library so that our app can use the basic building blocks Redux provides for fiddling with application state. Once the Redux library has fully installed, there is just one more dependency we need to deal with. Run the following command to bring over all the React Redux content: npm install react-redux Once this command has run to completion, we have everything needed to both build our React app and use some Redux magic in it as well. It's time to start building our app! Building the App The first thing we will do is clear our package of all unnecessary and extraneous files. Go to your src and public folders, and delete all of the contents that you see in both of those locations. Once you have done this, create a new file called index.html in your public folder and add the following HTML into it: