It’s been a while since I’ve been working with React — a Facebook library to build user interfaces using JavaScript — and there are a few concepts I wish I knew when I was just starting. This text is an attempt to summarize some patterns I learned during my experience so far — and also may be useful for developers who are just about to enter this awesome component-based world.
Stateful x Stateless Components
Just as Stateful and Stateless web services, React components can also hold and manipulate state during application usage (Stateful) — or just be a simple component that takes the input props and returns what to display (Stateless).
A simple Stateless button component that depends on props only:
And a Stateful counter component example (using Button
component):
As you can see, the last one’s constructor holds a component state, while the first one is a simple component that renders a text via props. This separation of concerns may look simple but makes Button
component highly reusable.
Container x Presentational Components
When working with external data, we can divide components into this two new categories. Containers
are responsible to reach data that lives outside React scope, like connecting to Redux or Relay — while Presentational
components are free of dependencies from the rest of the app, depending only on its own state or props received. Let’s take a users list as a Presentational
component example:
This list can be updated using our Container
component:
This approach divides data-fetching from rendering and also makes UserList
reusable.
Higher-Order Components
Higher-Order Components — or just HOCs — are useful when you want to reuse a component logic. They are JavaScript functions that take a component as an argument and returns a new component.
Let’s say you need to build an expandable menu component that shows some children content when user clicks on it. So, instead of controlling the state on its parent component, you can simply create a generic HOC to handle it:
This approach allows us to apply our logic to our ToggleableMenu
component using the JavaScript decorator syntax:
Now we can pass any children to ToggleableMenu
component:
If you’re familiar with Redux’s connect
or React Router’s withRouter
functions, you’re already using HOCs!
Render Callbacks
Another great way to make a component logic reusable is by turning your component children into a function — that’s why Render Callbacks are also called Function as Child Components. We can take an example of our expandable menu HOC and rewrite it using the Render Callback pattern:
Now we can pass a function as our Toggleable
component children:
The code above is already using a function as children, but, if we want to reuse it just as we did in our HOC example (multiple menus), we could simply create a new component that uses Toggleable
logic:
Our brand new ToggleableMenu
component is ready to be used:
Our Menu
component looks exactly the same as our HOC example!
This approach is really useful when we want to change the rendered content itself regardless of state manipulation: as you can see, we’ve moved our render logic to our ToggleableMenu
children function, but kept the state logic to our Toggleable
component!
This post is written by Gustavo Matheus.
Response to “React Component Patterns”