web-dev-qa-db-ja.com

React:参照値を失う

私は2つのコンポーネントを使用しており、このパターンを使用しています。子コンポーネントは、可能な限り分離したままにする必要があります-独自の検証エラーを処理しています。親コンポーネントは、子間に依存関係があるエラーをチェックする必要があります。したがって、私の場合:passwordフィールドと_password confirmation_フィールド。

これが私のコードです:

a)SignUp(親)

初期状態を設定します。

_ constructor() {
     super();

     this.state = {
         isPasswordMatching: false
     };
 }
_

render()メソッドで、子コンポーネントを出力しています。 callbackと呼ばれるpropを介して、親のthisをバインドしてメソッドisPasswordMatching()を伝播しています。目的は、メソッドが子コンポーネント内で呼び出されることです。

_<TextInput
    id={'password'}
    ref={(ref) => this.password = ref}
    callback={this.isPasswordMatching.bind(this)}
    // some other unimportant props
/>

<TextInput
    id={'passwordConfirm'}
    ref={(ref) => this.passwordConfirm = ref}
    ...
_

isPasswordMatching()メソッドは、パスワードが一致するかどうかを確認し(参照_this.password_および_this.passwordConfirm_を介して)、状態を更新します。このメソッドは子の内部で呼び出されることに注意してください(passwordまたはpasswordConfirm)。

_isPasswordMatching() {
    this.setState({
        isPasswordMatching: this.password.state.value === this.passwordConfirm.state.value
    });
}
_

b)TextInput(子)

初期状態を設定します。

_constructor() {
    super();

    this.state = {
        value: '',
        isValid: false
    };
}
_

ぼかしの検証が行われ、状態が更新されます。

_onBlur(event) {

    // doing validation and preparing error messages

    this.setState({
        value: value,
        isValid: this.error === null
    });
}
_

最新。コールバックプロップが呼び出されます。

_componentDidUpdate(prevProps) {
    if (prevProps.id === 'password' || prevProps.id === 'passwordConfirm') {
        prevProps.callback();
    }
}
_

問題

どういうわけか私の参照は失われます。シナリオ:

  1. 親コンポーネントはレンダラーです
  2. 子コンポーネントがレンダリングされます
  3. 私は入力フィールドの1つを入力して、それを取り出します(これによりonBlur()メソッドが呼び出されます)-状態が更新され、子コンポーネントがレンダリングされます
  4. componentDidUpdate()が呼び出され、prevProp.callback()も呼び出されます
  5. isPasswordMatching()メソッドに移動すると、_this.password_および_this.passwordConfirm_が出力されます。これらは、期待される参照値を持つオブジェクトです。親の状態を更新しています-コンポーネントがレンダリングされます。
  6. 次に、すべての子がレンダリングされ、コンポーネントが更新され、コールバックが呼び出されますが、今回は_this.password_および_this.passwordConfirm_がnullです。

なぜ参照が失われるのか私にはわかりません。私は何か違うことをするべきですか?前もって感謝します。

16
be-codified

重要な警告とともに react documentation here を参照し、refをいつ使用するか、または使用しないかについてアドバイスします。

参照されるコンポーネントがマウント解除されている場合、および参照が変更されるたびに、古い参照がnullを引数として呼び出されることに注意してください。これにより、2番目の例のように、インスタンスが格納されている場合のメモリリークが防止されます。また、ここでの例のようにインライン関数式を使用してrefを書き込む場合、Reactは毎回異なる関数オブジェクトを参照するため、更新のたびに、refはnullを指定して呼び出され、コンポーネントインスタンス。

15
Galeel Bhasha

これが@ be-codifiedの質問に答えないかどうかはわかりませんが、同様の問題が発生していることがわかりました。私の場合は、機能コンポーネントを使用したことが原因であることがわかりました。

https://reactjs.org/docs/refs-and-the-dom.html#refs-and-functional-components

Refと機能コンポーネント機能コンポーネントではref属性を使用できません。refが必要な場合は、コンポーネントをクラスに変換する必要があります。ライフサイクルメソッドまたは状態が必要な場合と同じようにしてください。
ただし、DOM要素またはクラスコンポーネントを参照する限り、機能コンポーネント内でref属性を使用できます。

ドキュメントは、レンダリングしようとしているコンポーネントを制御できる場合、問題を解決するために何をすべきかを説明しています。

しかし、私の場合、コンポーネントはサードパーティのライブラリからのものでした。したがって、コンポーネントをラップするだけで問題なく動作しました。

働く

<div ref={element => this.elementName = element}>
    <FunctionalComponent />
</div>

動作していない
this.elementNameをnullに設定します

<FunctionalComponent ref={element => this.elementName = element} />

これが私のようにこの質問を見つける人を助けることを願っています。

5
mawburn