1

ここでの反応の例に似たフィルター処理されたテーブルを作成しようとしています: Thinking in React。追加したいのは、アイテムの合計セットから表示されているアイテムの数です。私のアイデアは、状態変数「numShowing」を最上位コンポーネント「リソース」に保持することでした。また、setState() を使用して「numShowing」をインクリメントする関数をこのコンポーネントに作成しました。次に、その関数をコンポーネントのチェーンに渡し、対象のコンポーネントがマウントされたときに呼び出します。ここにいくつかの疑似コードがあります (不要なものとフィルタリングコンポーネントへの参照を削除しました):

コンポーネントの階層は、Resources -> ResourcesTable -> ResourcesTableEntry です。

var Resources = React.createClass({
  getInitialState: function() {
    return {
      numShowing: 0
    };
  },
  incrementShowing: function() {
    console.log('increment from: ' + this.state.numShowing);
    this.setState({numShowing: this.state.numShowing + 1});
  },
  render: function() {
      <div>
        <ResourcesTable resources={this.state.resources} incrementShowing={this.incrementShowing} />
      </div>
    );
  }
});

var ResourcesTable = React.createClass({
  createEntry: function(resource) {
      if (/* filtered out */) {
        return;
      } else {
        return(<ResourcesTableEntry key={resource.id} resource={resource} incrementShowing={this.props.incrementShowing} />);
      }
  },
  render: function() {
    return (
      <table>
          <tbody>
            { this.props.resources.map(this.createEntry) }
          </tbody>
      </table>
    );
  }
});

var ResourcesTableEntry = React.createClass({
  componentDidMount: function() {
    this.props.incrementShowing();
  },
  render: function() {
    return (
      <tr>
        /* output props here */
      </tr>
    );
  }
});

ResourcesTable.createEntry 関数からのインクリメントも試みました。どちらの場合も、numShowing は 1 に設定されるだけです。これは、setState が非同期または非アトミックであるためだと思われます。そのため、incrementShowing() へのすべての呼び出しが行われる時点で numShowing の現在の状態は 0 です (コンソール出力は関数を検証します)。正しい回数呼び出されています)。では、これを行う「正しい」方法は何でしょうか?

4

1 に答える 1

0

ここでの問題は、アンチパターンであるため、render メソッド内で状態を更新したくないことです。numShowingこの問題は、フィルタリングを所有するコンポーネントに移動することで解決できますResources。これにより、コンポーネントが不要になりResourceTableます。

var Resources = React.createClass({
  render: function() {
    numShowing = 0;
    filteredResources = this.state.resources.map(function(resource){
      if (/* filtered out */) {
        return;
      }
      numShowing++; 
      return(<ResourcesTableEntry key={resource.id} resource={resource} />);
    }.bind(this));
    return(
      <div>
        <span> Number of results: {numShowing} </span>
        {filteredResources}
      </div>
    );
  }
});
于 2015-03-12T01:57:15.997 に答える