【譯】容器元件 (Container Components)

樑仔發表於2019-01-11

medium 原文連結

對我的程式碼有最深遠影響的一個React模式叫 container component 模式。

Jason Bonta 講了如何建立高效能元件(High Performance Components),這個演講講的就是 container components

這個概念非常簡單:

一個 container 僅僅只是做資料拉取然後渲染它對應的子元件。

“Corresponding” 意味著分享同一個名稱的元件,例如:

(StockWidgetContainer) => StockWidget;
(TagCloudContainer) => TagCloud;
(PartyPooperListContainer) => PartyPooperList;
複製程式碼

這就是其中的概念。

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.

——完——

相關文章