web-dev-qa-db-ja.com

React:支柱が変更されても子コンポーネントが更新されない理由

次の擬似コードの例で、Containerがfoo.barを変更してもChildが再レンダリングされないのはなぜですか。

Container {
  handleEvent() {
    this.props.foo.bar = 123
  },

  render() {
    return <Child bar={this.props.foo.bar} />
}

Child {
  render() {
    return <div>{this.props.bar}</div>
  }
}

Containerの値を変更した後にforceUpdate()を呼び出しても、Childは古い値を表示します。

62
Tuomas Toivonen

なぜなら子供たちは親の小道具が変わったとしても、そのSTATEが変わったとしても再表示しません:)

あなたが見せているのはこれです: https://facebook.github.io/react/tips/communicate-between-components.html

それは小道具を通して親から子へデータを渡すでしょうが、そこに表現の論理はありません。

何らかの状態を親に設定してから、子を親の変更状態にレンダリングする必要があります。これは助けになるかもしれません。 https://facebook.github.io/react/tips/expose-component-functions.html

52

属性 'key'がnameと等しくなるようにchildを更新します。

Child {
  render() {
    return <div key={this.props.bar}>{this.props.bar}</div>
  }
}
12
PolinaC

Reactの哲学によれば、コンポーネントはその小道具を変えることができません。それらは親から受け取られるべきであり、不変であるべきです。親だけが子供の小道具を変えることができます。

state vs props についての素晴らしい説明

また、このスレッドを読んでください react.jsで小道具を更新できないのはなぜですか?

8
Sujan Thakare

setState関数を使うべきです。そうでない場合は、forceUpdateをどのように使用しても、stateは変更を保存しません。

Container {
    handleEvent= () => { // use arrow function
        //this.props.foo.bar = 123
        //You should use setState to set value like this:
        this.setState({foo: {bar: 123}});
    };

    render() {
        return <Child bar={this.state.foo.bar} />
    }
    Child {
        render() {
            return <div>{this.props.bar}</div>
        }
    }
}

あなたのコードは無効です。このコードをテストすることはできません。

6
JamesYin

SetState関数を使用してください。だからあなたはできる

       this.setState({this.state.foo.bar:123}) 

handleイベントメソッド内.

状態が更新されると、変更がトリガーされ、再レンダリングが行われます。

3
Indraneel Bende

私は同じ問題を抱えていました。これは私の解決策です、私はそれが良い習慣であるかどうかわからない、そうでない場合は教えてください:

state = {
  value: this.props.value
};

componentDidUpdate(prevProps) {
  if(prevProps.value !== this.props.value) {
    this.setState({value: this.props.value});
  }
}

UPD:React Hooksを使って同じことができるようになりました:(コンポーネントが関数の場合のみ)

const [value, setValue] = useState(propName);
// This will launch only if propName value has chaged.
useEffect(() => { setValue(propName) }, [propName]);
1
petrichor

子が状態を維持せずに単純に小道具をレンダリングしてから親から呼び出す場合は、おそらく子を機能コンポーネントとして作成する必要があります。これに代わる方法は、ステートレスコンポーネントを再レンダリングさせる機能コンポーネント(useState)でフックを使用できることです。

それらが不変であるのでまたあなたはpropasを変更するべきではありません。コンポーネントの状態を維持します。

Child = ({bar}) => (bar);
0
satyam soni