To be honest, this was my first impression of Redux/React-Redux. Redux is basically just another way to do state management, which is something that React can already do. For people that are familiar with React, the library already has the ability to work with the state object. We have the state object that is declared in components, along with the ability to manipulate that state. That's it, very straightforward. Redux takes this and for reasons we'll get into in the article, makes it much less straightforward. As I got into it though, I found that Redux definitely has its perks, which we'll get into.
To get an overview of Redux, let's first take a look at a diagram showing the cycle of Redux. Knowing these connections, will be key to understanding how Redux works, seeing the value in it, and hopefully, realizing that it's actually a neat mechanism.
Like we mentioned before, Redux is used primarily for state management. If you think about how state is managed, the two essential parts that we have to define are the way in which we want to change the state, and the state itself. We briefly mentioned how this works in React in our intro. Redux on the other hand handles these necessities of declaring state and changing state with reducers and actions. The way these differ from normal state call is that both reducers and actions are actually functions, and are organized in a way that they depend on each other. There are 5 different sections in our graph here, but we'll take a look at the diagram in terms of 3 main categories. Let's first take a look at what actions and action creators do.
Actions/Action Creators
Here is a simple example of what an action/ action creator. First of all, this is analogous to our setState function in normal React code, and is responsible for dealing with events that occur on the components and make a call to this function. It is the 'action' that is called to make a change to our state.
You'll notice that as we mentioned, there is foremost the function itself which is what we call the action creator. This action creator is a function that is responsible for taking input from wherever it was called on a component, and integrating that value onto an object, which is the action.
The action then, is the object which is created from the action creator function. This object is basically like a request with set of specificiations which let the redux machine know what kind of state change we want to happen, and what information it needs to make the proper changes. Those details as you'll notice in the code include the type and the payload. The type
key is one that is always required in an action, and that's because this key lets the store know what kind of reducer needs to process this action. We'll get more into reducers and store next, but for now, it's important to recognize that the type
key in the action is responsible for distinguishing what kind of state change will happen. Besides the type
key, everything else is option including the payload
key, which in this case simply takes in a song
variable. It doesn't have to be called payload
and just like any other object, you can define the key whatever you want in relation to the values.
Reducers
Next up we have the reducers, which we briefly mentioned in the previous section in relation to the type
variable, saying that it determines which reducer is used to process. To say it differently, actions simply pick which mechanism of state change is picked, but they don't actually define the mechanism. The reducer is the function responsible for defining that mechanism.
You'll notice again that reducers are simply functions. In our example code, we have two types of reducer functions. One of them merely defines an object and returns it, which is similar to initializing state in a component. The next function is a reducer which can induce state change, and this kind takes an state(in our case named selectedSong
) and action variable.
The first and most important variable is the state itself. In our case, our state variable is the initial argument of selectedSong
. This variable is then passed into the reducer function as the recorded previous state, and then whatever is returned from this reducer function then becomes the new state variable. Although we are passing this previous state into the reducer function for reference it is very important to note that you must not mutate the original state variable. You must instead, create a copy of that original state variable and then work with that copy (f.e. array.push(element) won't work, return [...array, element] works).
The other variable to note is the action, and we can recognize this from our last section. The reducer takes in the arugment of action, and checks its type
variable whether through if statements or switch statements, and proceeds to do a particular state manipulation. In our case, we simply checked for whether the action we were receiving had a type SONG_SELECTED
and if it did, we would return the state as the payload in the action, which was our song in the action argument.
One last detail to note is that the way these reducers are exported, require the redux function combineReducers
so that all the reducers can be put onto the store. The reducers that are included here define what the store variable is.
To mention that last sentence again in flow of the original graph, 1) we triggered the action creator function with a song variable 2) we created an action with a type and a payload of that song, 3) dispatch actions to the reducers(covering this next), 4) Our selectedSongReducer reducer receives the state and action variables and decide how to return the new state and 5) Our new state is now available.
Redux(store/dispatch) & React-Redux
Having talked about the objects of state change themselves in actions and reducers, we'll now cover the Redux and React-Redux libraries and how they are implemented in various React files to allow state functionality in our applicaton.
Let's first cover the two main topics we've already mentioned in exploring actions and reducers, which are the dispatch and store functions.
First, you'll notice that we create the store variable in our code. We do this by calling createStore
with all the reducers imported from the reducers folder that were exported using combineReducers
. This store variable is now the object that hold all of our state variables.
Next is dispatch, is not explicitly used her, because it will be taken care of in the React-Redux library, but this function is responsible for connecting any action to our store which is all of the variables. This ability for Redux to use an action for every single reducer(stage manipulator) at one time, is one of the things that makes it so powerful.
With the React-Redux library, dispatch is actually handled by the two main components we insert use to communicate state to our components: Provider and Connect.
Provider is seen here on the index.js level and wraps the whole App component with the created store variable. This allows the React-Redux Provider component to be aware of what reducers and state variables currently exist in the store.
This Provider component communicates to the connect component, which is defined in the component. You can see of how it's called in this code snippet.
Connect is called with the export default statement, and takes into the first function's parameters are first a function for converting state to props and the second is an object containing the actions we want to use in this particular component. That is followed by the Component's name itself in a separate function parameter. The function that we created called mapStatetoProps
is first of all called that by convention, and is used to take in the state from the store variable we just created on Provider, and convert this state to props. That function is also named that by convention, so you should always name it that. Now you can see that the props.songs variable is available to be mapped over in the function, and the selectSong action can be called in the onClick callback function. Our component can now refer to state and change it!
Overview
And there you have it, that is Redux. It seems almost unnecessary to go through the process of packing all these state changes in functions, but to close with a few advantages that is the reason why this library has becomes so popular.
1) State change becomes very manageable - You know exactly all of the possible ways state can change since given the same action and state, you will always receive the same results.
2) State becomes easy to access - You don't have to pass down the state through the props argument and potentially give a bunch of files, data it doesn't need. You can instead use the Provider and Connect of React-Redux to give components direct access to props.
3) State and actions are easily testable - All the ways state can be changed exist on one file and is manageable. Makes it easy to identify a bad state change function and fix it.
Top comments (0)