容器组件 (Container Components)

medium 原文链接

对我的代码有最深远影响的一个 React 模式叫 container component 模式。

Jason Bonta 讲了如何建立高性能组件(High Performance Components),这个演讲讲的就是 container components

这个概念非常简单:

一个 container 仅仅只是做数据拉取然后渲染它对应的子组件。

“Corresponding” 意味着分享同一个名称的组件,例如:

(StockWidgetContainer) => StockWidget;
(TagCloudContainer) => TagCloud;
(PartyPooperListContainer) => PartyPooperList;

这就是其中的概念。

为什么要用 container(Why containers?)

假设你有一个用于展示评论的组件。在你不使用 container 组件的时候,你会把所有代码都放在一个地方:

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>
    );
  }
}

你的组件就是用于拉取数据并展示它。这并没有什么错,但是你错过了一些 React 的优点。

可复用性(Reusability)

除非在完全相同的情况下,否则CommentList 组件无法被复用。

数据结构(Data structure)

你的标记组件应该给出他们所期望的数据类型。PropTypes就是做这个的。

我们的组件对数据结构要求很高但是没有办法说出这些要求。如果 json 的接口数据改变了,这个组件会不做出任何提示出错。(其实想说的就是,无法好好利用 PropTypes 来把控数据结构是否正确)

用 container 重写 (Once again. This time with a container)

首先,我们把数据拉取的功能放到 container 组件上。

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

  componentDidMount() {
    fetchSomeComments((comments) => this.setState({ comments: comments }));
  }

  render() {
    return <CommentList comments={this.state.comments} />;
  }
}

现在,我们修改CommentList让它接收comments 作为prop

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

我们学到了啥?(So, what did we get?)

我们实际上得到了很多...

我们分离了数据拉取和渲染(data-fetching and rendering)。

我们使我们的 CommentList 组件得以复用。

我们赋予了CommentList设置PropTypes和错误提示的能力。

我是一个container components的大粉丝。他们让我的 React game 有了很大的进步,并且使我的组件更加易读。试试,看看 Jason 的演讲。太棒了!

Carry on, nerds.

——完——

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容