avatarLearn React with chantastic

Summary

The provided content discusses the container component pattern in React, which separates data fetching from the presentation logic, enhancing reusability and maintainability of components.

Abstract

The React pattern known as container components is highlighted as a significant influence on the author's code structure. This pattern involves creating a container that handles data fetching and then passes the data to a sub-component responsible solely for rendering. The author emphasizes the simplicity of this approach, where the container and sub-component share the same name, as seen in examples like StockWidgetContainer and StockWidget. The benefits of using container components include improved reusability, clear data structure expectations through PropTypes, and a separation of concerns that makes components easier to read and maintain. The article contrasts a monolithic CommentList component that handles both data fetching and presentation with a refactored version that uses a CommentListContainer for data fetching and a CommentList for rendering. The refactored approach is advocated for its advantages in reusability, explicit data requirements, and failure robustness. The author encourages readers to adopt this pattern and to watch Jason Bonta's talk for a deeper understanding.

Opinions

  • The author views the container component pattern as a positive influence on their React codebase, suggesting it has significantly improved their development practices.
  • There is an opinion that combining data fetching and presentation in a single component is not inherently "wrong," but it does deprive developers of React's full benefits.
  • The author believes that components should be reusable and opinionated about the data structure they require, with PropTypes being a useful tool for expressing these data structure opinions.
  • The article expresses that the separation of data-fetching and rendering concerns leads to better component design, making components more reusable and maintainable.
  • The author is a strong proponent of container components, finding them effective in enhancing code readability and overall quality.
  • The author recommends Jason Bonta's talk on high-performance components as an excellent resource for further learning on the subject.

Container Components

One React pattern that’s had the impact on my code is the container component pattern.

In Jason Bonta talk High Performance Components, there’s this little gem about container components.

The idea is simple:

A container does data fetching and then renders its corresponding sub-component. That’s it.

“Corresponding” meaning a component that shares the same name:

StockWidgetContainer => StockWidget
TagCloudContainer => TagCloud
PartyPooperListContainer => PartyPooperList

You get the idea.

Why containers?

Say you have a component that displays comments. You didn’t know about container components. So, you put everything in one place:

class CommentList extends React.Component {
  this.state = { comments: [] };

  componentDidMount() {
    fetchSomeComments(comments =>
      this.setState({ comments: comments }));
  }
  render() {
    return (
      <ul>
        {this.state.comments.map(c => (
          <li>{c.body}—{c.author}</li>
        ))}
      </ul>
    );
  }
}

Your component is responsible for both fetching data and presenting it. There’s nothing “wrong” with this but you miss out on a few benefits of React.

Reusability

CommentList can’t be reused unless under the exact same circumstances.

Data structure

Your markup components should state expectations of the data they require. PropTypes are great for this.

Our component is opinionated about data structure but has no way of expressing those opinions. This component will break silently if the json endpoint change.

Once again. This time with a container

First, lets pull out data-fetching into a container component.

class CommentListContainer extends React.Component {
  state = { comments: [] };
  componentDidMount() {
    fetchSomeComments(comments =>
      this.setState({ comments: comments }));
  }
  render() {
    return <CommentList comments={this.state.comments} />;
  }
}

Now, let’s rework CommentList to take comments as a prop.

const CommentList = props =>
  <ul>
    {props.comments.map(c => (
      <li>{c.body}—{c.author}</li>
    ))}
  </ul>

Example Codepen

So, what did we get?

We actually got a lot…

We’ve separated our data-fetching and rendering concerns.

We’ve made our CommentList component reusable.

We’ve given CommentList the ability to set PropTypes and fail loudly.

I’m a big fan of container components. They’re stepping up my React game a lot and making my components easier to read. Give them a try and watch Jason’s talk. It’s excellent!

Carry on, nerds.

Check out learnreact.com for more references and tutorials.

Reactjs
JavaScript
Web Development
Recommended from ReadMedium