There isn’t really a “best practice” or “convention” when it comes to loading your data in React. This is actually a good thing, as it maintains the awesome part of React being very un-opinionated and letting you decide how you want to design your app.
However, too much flexibilty can lead to multiple developers on the same team doing the same thing in different ways. There is usually a style guide at most companies or a consensus about how certain actions should be done.
In this post, I will go through 3 different ways I have come accross for loading data in React. You can compare the pros/cons yourself and decide what approach would be best for you to do. After all, they all accomplish the same thing!
1. Container Components
Dan Abramov popularized the container/presentational component pattern back in March 2015. With this pattern, we would have container components that usually load data inside the
componentDidMount method, and once the data is loaded we render the presentatonal components. A simple example is as follows:
Let’s say we want to fetch the list of posts from the soccer subreddit and just dislay the title of each post as divs. Our container component would thus be responsible for fetching the data and would be as follows:
There are a few things to take note of here:
- We have a boolean on the state the determines when loading data is completed
- We are using the Promise based axios package for performing our HTTP request
- We are dependent on the component state to store our data
This approach is straight-forward and the code is still kept clean, as our presentational component can now be a simple functional component as follows:
- Easy to write/understand
- Very little dependency on other libraries
- Separates concerns (i.e. Container and Presentational Components)
- Not reusable: unfortunately if we want to use the list of posts somewhere else on our app, we either have to load the data again or somehow make the container determine which presentational component to render, adding complexity quickly
Only 1 con in my opinion for this method, but it is pretty major as any even moderately complex application will definitely share data accross different pages/components
2. Redux Async Actions
Redux is one of the most popular libraries for handling Application State right now. It uses the Flux implementation of loading data where you dispatch three differnet actions:
- Request began
- Request successful
- (or) Request failed
The documentation on this approach is great, and you should check it out if you are interested in the specifics.
- Excellent separation of different states of your app
- Data is saved in the store so can be used from within any component connected to your store
- A good pattern that will lead to well-organized files
- Lots of boilerplate
- Potentially bloats the store with data that only one component needs
- Not easy to understand the first time doing it
3. Hybrid Approach
My preferred way of handling data loading in React apps is to use a hybrid of both approaches. Stick with using the container/presentational pattern first, and only if you see yourself needing a datum in multiple components, then refactor to put it in the store.
I find with this approach you get the best of both worlds. You can write code fast, avoid unneccessary boilerplate, separate your concerns and share your data accross different components if needed.
One major concern I have heard from developers when I use this approach is that they don’t like to mix two different patterns. This is valid but my arguments are as follows:
- Both patterns are accepted and battle-tested in the React community
- You do not need to bloat your application state with data that only one component uses; it will become a pain to manage after a while
- This approach allows you to build features fast
The React community will likely never reach a consensus on what the best way to load data is. I have outlined 3 different appoaches in this post that I believe are all valid, and it is up to the team to decide which works best for them.