When rolling out a mobile app, one of the first decisions you usually make is: what language do we use? After some deliberation, and when you come to the realization that you don't want to learn Kotlin and Swift, you finally settle on React-Native. From my own experience, learning a new “language” or framework isn’t a huge issue, but man oh man, did react-native and redux give me a hard time. This article doesn’t explain how React-Native works (as that is not the hard part). The purpose of the next few paragraphs is to help anybody reading this transition from “thinking in MVC” to “thinking in Redux”. Hope it helps.
As soon as you start learning about react-native (or react), you are about 3 stack overflow questions or medium posts away before somebody mentions redux.
You were so happy. You started to understand state vs props, you know what componentDidMount does and you even understand how to properly create your components so they are re-usable. Now all of a sudden you found yourself on egghead.io, and some guy is talking about stores, reducer compositions, actions and mapping state to props.
You also realize that while before you were able to do: $(“.my-button”).click(); to get a button to do something; it has now been about 3 hours and your one button doesn’t do anything.
If you are coming from an MVC (or MVVC) world, you are used to models, views and controllers (duh). However in Redux we are dealing with actions, reducers, stores and components. Trying to “translate” MVC to Redux is tricky but here is how I would do it:
Actions = Controller. Think of your actions as the controller. Whenever you want something to happen in your app (i.e. load some data, change a isLoading flag from true to false…) you will have to dispatch an action. Just like in MVC where you would have to call a controller endpoint.
Reducer = Model. Sort of. Your reducers will be in charge of holding the current state of your application (i.e. user info, information loaded from the api, items you want to display…). It will also be the part that decides what to do when an action is called. While in MVC you might have a model with the method setName(), with Redux you would have a reducer handle an action to set the name in the state.
Stores = ???. The store is Redux specific and doesn’t really have an equivalent in MVC. Not to worry though. This part is taken care off behind the scenes. The store is like a container for the state that aggregates all of the reducers. It has a method to the get the current state, and exposes ways to subscribe to the state changes (using the “connect()” method). This is what will allow you to call actions and pass them in as props to your components.
Components = Views. Components are kind of like your smart views. They display the information that they get from the state. I recommend splitting up your components into two parts. One just for the presentational part (dumb components) and one to handle all of the actions and state changes (smart components).
pssst I tweet about code stuff all the time. If you have questions about how to level up your dev skills give me a follow @mlevkov
As you can see (and know from experience) in the diagram above data can flow two ways. You press a button in your view, it sends a message to the controller and that updates the model. The model changes some value, returns the value to the controller, and the controller refreshes the view. Easy peezy!
With Redux things work a little differently. Let’s say you have a component and you want to do something when a button gets pressed. Where do you start? Here is how I go about it.
- Define your Action
- Define your Reducer
- Define the Actions as a Prop in your Component
- Wire it up in your View
Here is a simple code example to explain these concepts. In this example I will show how to edit a text input and when a user presses a button it will call an action to save it.
First let’s start with the Action file.
Now onto our Reducer. Basically, the reducer has to handle the actions that come in.
Notice how the constants.MODIFY_NAME and constants.SAVE_NAME are exactly what is being returned by our actions in the type field. That is how you let the reducer know what action is happening.
Now to define our “smart” component. Really all this means is this is the component that will define the call to the actions.
Now for the easiest part. You create your presentational component that the user will interact with (the V in MVC).
And that’s it! You still have to do some basic boilerplate setup stuff, but I hope this clears up how to think in redux.
This was something that tripped me up for a little while (i.e. what information was being passed where and how…) so I’m hoping to save you guys some time and heartache.
If you want to level up your coding skills, I’m putting together a playbook that includes:
- 30+ common code smells & how to fix them
- 15+ design pattern practices & how to apply them
- 20+ common JS bugs & how to prevent them