1. ホーム
  2. reactjs

[解決済み] ReactJSのステートとプロップ

2022-09-04 17:35:27

質問

これは、回答可能か意見かの境界線を踏むかもしれませんが、私は複雑さが増すにつれてReactJSコンポーネントをどのように構成するかについて、行ったり来たりしており、いくつかの指示を得ることができます。

AngularJS から来て、私のモデルをプロパティとしてコンポーネントに渡し、コンポーネントがモデルを直接修正するようにしたいのですが、どうすればよいでしょうか。それとも、モデルをさまざまな state プロパティに分割し、上流に送信するときに一緒にコンパイルする必要がありますか?ReactJSの方法は何ですか?

ブログ記事エディタを例にとってみましょう。モデルを直接変更しようとすると、次のような結果になります。

var PostEditor = React.createClass({
  updateText: function(e) {
    var text = e.target.value;
    this.props.post.text = text;
    this.forceUpdate();
  },
  render: function() {
    return (
      <input value={this.props.post.text} onChange={this.updateText}/>
      <button onClick={this.props.post.save}/>Save</button>
    );
  }
});

というのは間違っているようです。

むしろReactのやり方は、私たちの text モデルプロパティ state のように保存する前に、モデルにコンパイルし直してください。

var PostEditor = React.createClass({
  getInitialState: function() {
    return {
      text: ""
    };
  },
  componentWillMount: function() {
    this.setState({
      text: this.props.post.text
    });
  },
  updateText: function(e) {
    this.setState({
      text: e.target.value
    });
  },
  savePost: function() {
    this.props.post.text = this.state.text;
    this.props.post.save();
  },
  render: function() {
    return (
      <input value={this.state.text} onChange={this.updateText}/>
      <button onClick={this.savePost}/>Save</button>
    );
  }
});

これは this.forceUpdate() を呼び出す必要はありませんが、モデルが大きくなるにつれて(投稿は著者、件名、タグ、コメント、評価などを持っているかもしれません)、コンポーネントが本当に複雑になり始めます。

最初のメソッドは ReactLink を使う方法がいいのでしょうか?

どのように解決するのか?

あなたの2番目のアプローチがより近いです。React はモデルについてそれほど気にしません。 とそれらがどのようにアプリ内を流れるかを気にします。理想的には、投稿モデルはルートで単一のコンポーネントに格納されます。その後、モデルの一部を消費する子コンポーネントを作成します。

データを変更する必要がある子コンポーネントにコールバックを渡し、子コンポーネントから呼び出すことができます。

this.propsやthis.stateを直接変更することは、Reactが変更を拾うことができないため、良いアイデアではありません。Reactはpost propが変更されたかどうかを判断するために、浅い比較を行うからです。

私が作ったのは、この jsfiddle を作成し、外部コンポーネントから内部コンポーネントへのデータフローを示しました。

handleClick メソッドは、状態を(誤って)適切に更新する3つの方法を示しています。

var Outer = React.createClass({

  getInitialState: function() {
    return {data: {value: 'at first, it works'}};
  },

  handleClick: function () {

    // 1. This doesn't work, render is not triggered.
    // Never set state directly because the updated values
    // can still be read, which can lead to unexpected behavior.

    this.state.data.value = 'but React will never know!';

    // 2. This works, because we use setState

    var newData = {value: 'it works 2'};
    this.setState({data: newData});

    // 3. Alternatively you can use React's immutability helpers
    // to update more complex models.
    // Read more: http://facebook.github.io/react/docs/update.html

    var newState = React.addons.update(this.state, {
      data: {value: {$set: 'it works'}}
    });
    this.setState(newState);
 },

  render: function() {
      return <Inner data={this.state.data} handleClick={this.handleClick} />;
  }
});