The Flux application design pattern is still going strong and gaining popularity. There are countless libraries around, helping you implement Flux. But lately, one has been standing out.
Redux is definitely the most simple implementation of Flux I have seen so far and it’s very functional too, actually, it’s just a bunch of functions!
So what is redux all about? Given, it’s an implementation of Flux. But it looks quite different (all examples will be in ES6). We are going to cover the three basic concepts: the store, reducers and actions. Let’s start with the store. So how do you create one in redux ?
Yes, just one line (excluding the import). And this is the last store you will need, yes, only one. Your application will have one store with one big object containing you application state. So what is that reducer all about?
But what will trigger the store to update it’s state? That’s where actions come in to play, they are also just … functions!
Again: no side effects, no magic. This action just takes an amount of money and returns an action object. The action object is essentially a message that you send to the store and tells the reducers what to do. The object composition is completely up to you, but following the Flux pattern, at least specify the type of the action. String constants are an easy way to specify types.
Now let’s modify our reducer to handle this action:
So, we start off with a default of 0 money. Then if an action is fired, we check if it is an _ADDMONEY type action. If it is, we return a new state with the money added. If it is not an _ADDMONEY type action we do nothing, we just return the old state.
Notice how we don’t modify the old state, this is a very important fact. Always return a new state, never mutate the old state. You could use a library like ImmutableJS to assure this behaviour, or use Object.assign(..) to create a new state every time.
So, how do we fire off this action? I mean, we need some money right?
One line, that’s it! addMoney will return an action object of type ADD_MONEY with an amount value of 1000000. The store will pass that action to the reducer, which will determine the new state. This new state is then stored in the store and can be accessed like this:
So to recap. There are three main concepts in redux. The store, actions and reducers. Actions trigger state changes, the store holds the state and reducers calculate the next state. Here is a simplified scheme of how the redux cycle works:
Actions are triggered by either views, other actions or events/callbacks from, for instance, the server.
Let’s say our application has a bigger state then just money. Let’s say it has money and awesomeness. How do we do this? We can just create 2 reducers!
And then combine them like this:
This will result in both reducers output being combined into one object. We could also use a helper provided by redux:
This has the exact same result and is completely optional, but can be more convenient.
Get state still works the same, but now it returns an object with two properties:
The store updates the state according to the action you pass to it. There are no weird side effects, just simple input output logic.
So how do we wire the store up to a view? I mean, all this stuff is fun, but we want to interact with it right, otherwise what’s the point? Let’s do this example with, yes, React.
First we create a React Component:
This component needs the money and awesomeness props to be passed to it. It will then render a nice message about me and a button to give me more money :). If someone clicks the button, the giveMoney method is called. It will need the dispatch function from the store (also passed via the props) and then pass the addMoney action to the dispatch function.
Now we have to connect the component to redux, so that it can pass us the money and awesomeness props. To do this we will use the package ‘react-redux‘, which will ‘connect‘ our view to our store. This will let the view update automatically when the state of the store changes.
First we import the connect function and the Provider component from ‘react-redux‘. Then we connect MyCoolComponent to the store. The connect method takes a function that allows you to control how the state is passed to the component. For now just (state) => state will be sufficient. Then we pass MyCoolComponent to the function connect returns, our component is now ready for connection with redux.
At last we render our component into the DOM, but we wrap it in the Provider component. We pass the Provider component the store, the Provider will now connect the ‘connected‘ components inside of it with the store. And that’s it. Our component now updates when the state of the store changes.
I think this is enough for this article. If you are confused right now, don’t worry, it takes some time to get your head around the concept. It’s a bit different from what you might be used to. There is a lot more you can do with redux (like middleware, debug tooling) and it has a very vibrant community around it. The documentation of redux is very good and the library is maintained actively. The only way to learn more about it, is to play with it! Happy playing!