Most of the concepts in React are manageable. The hardest part, in my opinion, is state management.
What is “state”?
Program state has a long history in computer science, but essentially it’s just the “condition” that our program is in. If we’re rendering a tweet, then its state will be things like contents, the number of likes, the number of retweets, whether it’s expanded or collapsed, etc.
In traditional server-rendered apps we don’t have to worry about state changes. If a user interacts with your application or refreshes the page, then we’ll look up state at that moment and rebuild the page.
In dynamic apps, like ones built using React, state change has to be dealt with immediately. If a user clicks “retweet” then the rendered tweet needs to change instantaneously.
If your app is very dynamic (hence React) then you’ll be juggling a lot of states. To complicate things even further, what if someone from a different computer clicks “retweet” – how do we update state for everyone looking at that tweet? Moreover, some states are user-specific and possibly not saved at all, for example, whether navigation on the page is fully open or collapsed.
Facebook suggested a pattern called “flux” that can be very useful for managing a UI’s state. There are three main points:
- single source of truth
- top-down data flow
- state is changed through actions
There’s a library called Redux that implements this pattern. You might not need Redux though, especially for smaller applications. The following describes one way to manage state without using Redux.
Single source of truth
Managing state can get complicated if each component has some state. The users will start to experience inconsistencies. For example, in an email client, the header shows that you have two unread messages while the inbox itself is empty. One solution to this problem is to have a single place where we store state. This “store” is the single “source of truth” in the application.
Keeping state centralized is a concept that we have embraced on the server-side by using one database so doing the same for the client-side seems reasonable. As a compromise, especially in the prototyping stage, we can use “container components” instead of a single store.
Container components handle state for many child components.
Top-down data flow
The child components are stateless functions and get all of their data as properties from the container (parent) component. These are simply visual components.
The above is called a stateless functional component. These functions don’t have state or life-cycle methods. React encourages their usage because they’re easy to test, compose and reuse.
State is changed through actions
Functions are passed down to the child components to handle actions. Interaction with the components, like a mouse click, trigger these functions to update state. For example to implement retweets:
When the state is updated, the props will change too and render the child components again.
Your application might be composed of multiple container components. As the app gets more complex, with this approach, it will be easier to graduate to a solution like Redux.
properties flow down; actions flow up