React — Redux, the roadmap

Image for post
Image for post
how data flows in a React-Redux application

There are many react-redux guides out there, i mean so many. when I started learning React and Later Redux, I really was surprised by how many good articles there were to learn from. but something I couldn’t find was the whole picture in front of my eyes, just like a map when you look at it and you know where are you going.

Neither React nor Redux are difficult frameworks to learn, at all. the only thing you need to know is Javascript. So let’s get to business, what is this picture all about? simply put, it’s about how data flows, and that’s the key when it comes to Redux. you should be searching this on Google if you want to learn Redux quickly. yes all the ES6 tricks are very handy but that comes next. So let’s read this map together.

Image for post
Image for post

this is where it always starts, we render out <App />, there are two important notes though, <Provider> and {store}. <Provider> comes with React-Redux library, I won’t be going into so much details on how <Provider> works, since there are many other articles on the matter, i’ll just say that <Provider> is the Redux way of dealing with Context, and Context is when we bypass the React hierarchy of Components and give any child access to the store (In React terms, just a global variable). And {store} is what we import from our Store :) ( we’ll get to that).

Then we have our App, it imports Connect and bindActionCreators, respectively from React-Redux and Redux libraries. Connect has the task of well, connecting our component to the Provider, which provides access to the store. So we are starting to see the flow of data here, first index.js wraps our root component with <Provider>, i. e. provides it the store, then the component Connects to it. Connect can subscribe our React component to the changes in the store, and call the mapStateToProps any time the state inside store changes. There is also mapDispatchToProps which we use to map action creators from actions.js (this is the next stop) to functions on props that can be dispatched from our component. Being dispatched in terms of Redux means, they are going to update the state inside our store. bindActionCreators is there to, as it says, bind action creators, to dispatchable functions. So we click the doAction button now, that’s when actions.js comes into play.

Image for post
Image for post

As we see, we have an action creator called doAction in our actions.js. what actions do is the simplest part of Redux, they just start the process of mutating the state. any action must have an action type, and optionally a payload. Our App has only two action types, ACTION_START and ACTION_SUCCESS. Let’s say our doAction button, is responsible for opening a websocket connection to a server. That’s an async task, and you don’t normally do async in actions (you’ll need a middleware for that, thunk for example). You have two options here, you should move the async operation logic outside of doAction, or, ( the better way ) you can use the middlewares. So before getting to middleware, we can recap quickly, actions.js contains a seires of action creators, which when executed, become actions, these actions need to be dispatched in order for Redux to see them, dispatching happens within our <App /> with the help of bindActionCreators. Given that we are going to do some async operation, we define an action creator for the component to use, and another for the action itslef to call when it has finished its async operation. that’s why we have the actionDone function. By dispatching the ACTION_START, the middleware intervenes and that’s what we examine next.

Image for post
Image for post

Usually middlewares won’t come into play from the beginning when you start learning Redux, but they have nothing special, and in my opinion must be part of the beginner tutorials of redux as well. If you have worked with Node before, they come up all the time. The idea is just to intervene the process of dispatching actions. Our middleware here is ( as we were saying before ) responsible for opening the socket and connect to the server. So we listen on ACTION_START action, that’s when someone has clicked the doAction button, so the doAction action creator dispatches the ACTION_START action, ( sorry, that is a lot of action in a sentence! ), as its payload it has a reference to a function called actionDone, which should be called when the socket is open. The middleware intervenes on ACTION_START, does the socket stuff and when it’s done, dispatches the action passed to it on the payload like this: dispatch(action.payload.onSuccessCall()) When this executes, the actionDone action creator is called, and the ACTION_SUCCESS action is dispatched with the payload saying it’s ready. Again the middleware intervenes, but it has no case for the ACTION_SUCCESS, so it falls back to default case and passes the control to the next middleware doing next(action), since there are no more, the Reducer receives the action. To understand how exactly the internals of a middleware work take a look at this great article : Understanding Redux Middleware by @Mark.

Image for post
Image for post

So we’ve arrived all the way to the Reducer, where the state mutation actually happens. Reducer is the key concept in Redux, And its name says it all, it reduces all the user interaction, function calls and dispatches to a change in the state, in order for the action to become data. We see here that our Reducer listens on ACTION_SUCCESS and not ACTION_START. You can totaly do that of course, you can have a spinner_status in your store so it begins to spin when the ACTION_START is dispatched and you can add a case for that in your Reducer to hide it when the success callback action is dispatched. For simplicity we only catch the ACTION_SUCCESS. As you can see in the Reducer we catch the dispatched action and using its payload we update the store. Be careful that the blue arrow entring reducer_1.js comes from the default case of our middleware. So using the middleware we could transform the dispatched action into another action, and that feels natural no? When we clicked the doAction button, we were only starting the action, and then the middleware came and did the action and dispatched another one. So in the Reducer we return the mutated state, but to who? to the store, but there is another step before that.

Image for post
Image for post

The reducer_index, is fairly simple, it combines the reducers ( the idea is you separate different entities into their own reducers), and the combined object will be passed to the store as rootReducer. Redux’s combineReducers function, internally returns a function called combination, this function extracts state and actions from the Reducers, then iterates over all keys passed to combineReducers, calls the Reducer function with the current state and action, recreates the next state object and gives it to the store(the next state can also be equal to the current state). So every time our middleware dispatches an action, reducer_index.js calls all the reducers and recreates the next state. Now we’ll take a look at store.

Image for post
Image for post

We’ve finally arrived at the store, where it all comes together. The configureStore function that we pass to index.js as our store just returns the createStore function from Redux. This function accepts three arguments, reducer, preloadedState and enhancer. reducer we have discussed how is created. the initial state you can pass when doing server-side rendering. In any case before returning from createStore Redux dispatches an INIT action (a string like “@@redux/INIT…”), in order to get the initial state of every reducer. The last argument was the enhancer. Enhancers can be very helpful during the development as well, using the awesome redux-devtools-extension you can take advantage of what’s called as time-travel, but that’s for another day. We are passing the applyMiddleware as the enhancer, what is does is simply allows us to use middlewares, you should be careful that they get called in the order you introduce them here.

Image for post
Image for post

So now you should know exactly how the store object here is constructed and passed to <Provider>, and <Provider> only renders its children and passes through the new state object. Now our App can re-render and we will see the result of our doAction button!

Ah! I didn’t talk about the grey box, action_types.js, actually that’s fairly straightforward, this is the place we export our action types, just a series of strings we use for our switch cases in action.js, reducer.js and middlewares.js.

Hope you learned something from this article, I know I didn’t get very technical on every detail, but this article is here to help you picture the general idea behind how Redux works with React.

Written by

Developer in Berlin, like javascript, playing with algorithms 𝚯, photography 📷, novels 📖

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store