After React Baby Steps it was time to learn Redux. Yes, because it’s popular, but also because I’ve found that my React Redux-free app has one top component propagating props to the leafs of the component tree. So components in between, even if they don’t need some props, have to receive them just to propagate them down. Redux manages state and allows us to access it from any level in the component tree.
After some basic courses, even if straightforward, I had to bang my head one whole day (and night) to be able to properly refactor plain React app to Redux version. That’s why this early article on my Redux learning path, to summarize and share my findings. Here you can find my first Redux version of the app.
Note: Redux can be used without React, but I am assuming React-Redux usage.
- Getting Started with Redux – basic React video course from Dan Abramov – the creator of Redux
- Source Code for the course above for each chapter
- Source Code in the form of well structured React app (highly recommended)
- Notes (and partial transcription) of the course
- Redux Official Website
Presentational and Container Components
It’s important to understand this topic. Presentational components already have data and handlers provided via props, so they can only worry how to render data and call provided functions. Container components are opposite – they are not concerned about UI, they provide data and business logic for presentational components.
In Redux we create container components with connect function by providing data and behaviour which in return gives us HOC to enhance our component. That way enhanced component will have everything automatically without worrying how to get it. If you check my app here you can find presentational components in the components folder and container components in the containers folder. There is no strict rule how to do it. For example, App component is a container. It prepares initial state and provides some data for presentational component below (ReactCountries). Then ReactCountries is presentational component that uses some props to render and callback, doesn’t have any business logic and has both presentational and container components inside. Other container components inside are preparing things relevant for different parts of application (toolbar, list, add dialog, etc). That way we don’t have to propagate everything from the top, but introduce containers where it makes sense to provide data for underlying presentational component.
I highly recommend Thinking in React, it will also help you to understand this topic and structure your React app properly. Don’t worry, it takes some time to get it.
State, Reducers and Actions
One of the first things you will do in Redux app is to think about state/reducer organization and actions. Each reducer has it’s own corresponding part of the state object, is responsible for it and is not able to access other parts of the state. There is no strict rule here, for example – I have 3 reducers: countries (managing array of user’s countries), allCountries (managing DB of all countries) and ui (managing various parts of UI state like filters, visibility flags, messages, etc). Check Dissecting Twitter’s Redux Store to get an idea how smart guys design their store.
For now I feel that it makes sense to keep logic in reducers and make actions thin.
Preparing State Data in Container Components
In pure React app when you need to prepare some data (using API/DB for example) in the state, you can easily do it in componentDidMount lifecycle method of the top component (has access to this.state). But in Redux app, state is not managed anymore by React and I’ve lost some time to realize how to do it, although it’s very simple. Problem is that you don’t have access to dispatch from lifecycle methods, so I didn’t know how to store data in the state when ready. If you take a look at App container component, you will see that solution is to add fetching logic in mapDispatchToProps where you have access to dispatch, then to enhance current container component using connect (and not underlaying presentational component) so that it can access this.props.someFetchingMethod from componentDidMount and then just to render underlaying presentational component, passing required props down.
Accessing State Data from Reducers
Sometimes you will need to access some state data from reducer that doesn’t have access (manages other part of the state). My current solution for this is to pass required state data down as props to component that will in the end invoke handler and pass data back to action creator which will pack data in the action and that way make it available to any reducer.
I am not sure what is proper terminology, but I’ve stumbled upon this problem – let’s say I dispatch one action, there is some logic going on in the reducer and depending on some condition(s) I maybe want to invoke another/second dispatch. Example: 1) save something to DB and 2) if successful – show message. With current (basic) knowledge I am not aware how to do it.
- Building React Applications with Idiomatic Redux – this course will pick up where we left off with the Redux fundamentals course.
- React Countries refactor v2 with new Redux knowledge
- New blog article 😀
I was first sure that Redux is simple because it only has to manage state. Then I realized it has many components, but seems logical. Then when I tried to apply it, I had more questions than answers and had an impression that it’s too complex and difficult. Finally I made transition from pure React to Redux app and it looks OK. A little bit more complex, with more files and code and more time consuming, but it is giving me hope to continue with more advanced topics and see the real power of it.