This blog post is the first part of a series. You can find the summary of day 1 – part 2 here. We’ll update it with links to the other parts as they are published
For the last couple of days I’ve been attending a workshop held by the creators of Redux. The venue was at Espace Charenton in Paris, France. Around 100 developers from many different countries attended the workshop and the atmosphere was very open and relaxed, with plenty of opportunity to find people to chat and exchange experience with, as well as discuss solutions to various problems we had encountered during our usage of Redux and React.
- The first day of the workshop was dedicated to understanding React, Redux and reducers
- The second day we cloned a repo with problems where each problem built upon the previous one. More on this in an upcoming blogpost
The exercises for the first day had been written on JSBin and we initially had some technical difficulties when 100+ people tried to access the same exercise. While a bit annoying, it was also pretty entertaining to see the screens on every laptop and the big screens in the venue display a “loading bin” at the same time. Eventually we gave up on JSBin and moved the exercises over to JSFiddle.
“Could everyone please close your tabs so we can access the exercises and copy them over to JSFiddle?”
– Dan Abramov, React Europe 2016
On to some of the exercises we did during the day.
Exercise 1 – Write a counter reducer
So the first exercise to get us up to speed and to ensure that everyone had at least a basic understanding of the concepts in Redux, we were asked to implement the classic counter reducer. This reducer can pretty much be seen as the “Hello World”-reducer in the realm of Redux. If you look at the tests, it is supposed to handle only two types of actions:
"DECREMENT" which increase the counter by 1 or decrease the counter by 1, respectively.
A reducer in Redux has the following signature:
(state, action) ⇒ state. This means that it takes its current state and an action and the return value of the reducer is the next state resulting from that action. By convention, each action in Redux is an object which, at the very minimum, contains a `type`-property of type string that describes the type of the action. Armed with this knowledge, we’re ready to implement the solution:
After we’ve implemented the
counter-reducer, writing a reducer that manages a collection of reducers is pretty simple. We assume though that we modify the actions slightly, by adding an
index-property to the action object that indicates which counter the action applies to:
Exercise 2 – Creating a Counter Using the Store API
The second exercise tasked us with subscribing to the store using the
createStore(reducer, [preloadedState], [enhancer]) function from Redux. This is very straightforward and thus does not warrant much of an explanation. We have our reducer, we don’t have any state we need to rehydrate and in this case we do not want any store enhancers:
Implementing `createStore()` is pretty interesting. Basically, once you do this, you’ve implemented the core of Redux. Of course, in the real implementation there are a lot more code checking for error conditions, sanity checks and utility functionality. But basically, this is what Redux provides us:
- Keeps track of our reducer and the current state of the application
- Allows us to query the store for the current state of the application
- Allows us to update the application state by dispatching actions
- Allows us to subscribe to the store to receive updates to the state of the application
So, while learning Redux can seem daunting at first since there is a lot to grasp and take in when you combine it with bindings to React, selectors, reducers, action creators and what have you, it all boils down to just the bullet points above. It isn’t much more to it than that. Without further ado, here is Redux in 21 lines of code (not counting the comments):
Exercise 3 – Adding React to the Counter App
The third exercise was, at least if you’re familiar with React, also very straight-forward. Just clean up the code, create a component, render it with ReactDOM and ensure that we re-render using ReactDOM whenever the state changes. By re-using our naïve
render() function from the previous exercise, but instead delegating to ReactDOM to do the actual rendering very little extra code was needed:
The bonus exercise was also straightforward. We need to utilize another root reducer though, the one created in the bonus task of exercise 1. Additionally, we need to tweak our actions to include the index of the counter that is to be increased.
Exercise 4 – Writing a Todo List Reducer
For the fourth exercise, we got to write another classic reducer. A reducer for todo items. This example has been used many many times as it is simple enough to use in different comparisons between frameworks, while still being complex enough to be interesting.
One interesting thing to note here is that the supplied tests use
deepFreeze on the
action. This is a great way to ensure that the reducer does not try to mutate the state or the action. This is one of the invariants of a reducer in Redux. Never ever mutate the state, you need to return a updated state. We’re supposed to handle
"TOGGLE_TODO". Both of these could mess up this invariant if implemented incorrectly. For the
"ADD_TODO" case we need to ensure that we do not
push() the new todo item into the state. Rather, we need to create a new array and add the todo action to that array. For the
"TOGGLE_TODO" case we need to ensure that we do not mutate the todo item, and we also need to create a new array for the todo items, since we can’t replace the old todo item with the new one in the state. Why not? Well, that would be a mutation and is thus strictly forbidden.
End of part 1
This concludes part 1 of the summary of the workshop held by Dan Abramov and Andrew Clark at React Europe 2016. Stay tuned for the a walkthrough of the remaining four exercises we did during day 1, as well as the upcoming parts on day 2 of the workshop.
More in this series
- Day 1 – Part 1
- Day 1 – Part 2
- Upcoming: Workshop on Redux by Dan Abramov and Andrew Clark – Day 2