Sunday, August 30, 2020

Redux - How does Redux work?

 Now that we have a pretty good idea of the major problems Redux was created to solve, namely props drilling, state sharing, and global state chaos. Let's take a look at how it actually works. Well the name Redux might intimidate a lot of people, as names that end in 'x' tend to do, it's actually a fairly straight forward concept and process. Earlier, we learned about both the benefits and perhaps more importantly the rather crippling drawbacks of having a single, unrestricted global state that's accessible by all our components. That being said, one of the core concepts of Redux is that we have one central, global state called the store that all our components can access. Now this store is essentially a big J-son object that serves as the single source of truth for all of our components. And in theory it can hold any kind of data that we need it to. Although in practice there are some things that are better off without it, but that's a discussion for another time. So for example our Redux Store can hold data about the users, such as whether or not the user is logged in, the user's name, age, and bio, and what other data we might load from the server. 


 It can also hold things like a list of products on an e-commerce site, or a list of articles on a blog site. Basically, anything that we load from a server or any internal application state that we need to keep track of can be put into the Redux Store.


So the next question here is.. Since Redux uses a global state, how does it prevent the chaos inherent in this approach? Well, the problem with a global state isn't the fact that it's global per se, the problem is that there's no good way to control the excess and modification of this global state by pretty far flung parts of the application. This means that with an unrestricted global state, any part of our application can make whatever changes it wants to the global state basically without any restriction whatsoever. So we'd be relying on all our components to be good stewards of this state and change it in predictable ways, which from a software development standpoint, is a very naive assumption. 


 So in order to see how Redux solves this problem, let's take a look at the two other pieces of the Redux flow. We've already talked about the Redux store, which contains the current state of our application, but in addition we have Redux actions and something called reducers. 

Let's discuss both of these intern. Redux actions are j-son objects, consisting of two things, an action type, which is basically just a string naming the action, and a payload of additional data. The purpose of redux actions, is to explicitly define the different events that can occur in our application. So for example, we could have an action with the type: user data loaded, with a payload that contains the actual user data that we just fetched from the server. Or we could have an action with the type: item added to cart with a payload that contains the idea of the item that the user just added to their shopping cart. Now obviously the number of possible actions in an application can be pretty large, but the point here is that we're explicitly defining them, instead of just leaving it to chance. So that's actions,

 reducers on the other hand are Redux's way of specifying what should happen to our Redux store, our central state, when a given action occurs. So using our example from before, we might say that when a user data loaded action occurs, we set the user property in the Redux store to the user data that's in the action's payload. Or when an item added to cart action occurs, we add whatever item is in the payload, to the array of items in the shopping cart property of our Redux store. So the key point to know here is this: our components are only allowed to make changes to the state by triggering these predefined actions and the only changes to the state that are allowed to take place in our application are the corresponding changes that we specify in our reducers. This all gives rise to what's referred to as unidirectional data flow, in other words, we end up with a cycle that looks something like this: the UI triggers an action, that action is reduced to get the new updated state, and the components in our application get read only access to that updated state. We'll go into more detail about this in videos that follow, including what all this looks like in code and how components can access our store and trigger actions.