「exhaustive-deps」の lint ルールを理解するのが困難です。
私はすでに読んだこの郵便受けそしてこの郵便受けしかし、答えを見つけることができませんでした。
以下は、lint の問題がある単純な React コンポーネントです。
const MyCustomComponent = ({onChange}) => {
const [value, setValue] = useState('');
useEffect(() => {
onChange(value);
}, [value]);
return (
<input
value={value}
type='text'
onChange={(event) => setValue(event.target.value)}>
</input>
)
}
onChange
依存関係の配列に追加する必要がありますuseEffect
。しかし、私の理解ではonChange
決して変更されないので、そこには存在しないはずです。
通常、私は次のように管理します。
const MyCustomComponent = ({onChange}) => {
const [value, setValue] = useState('');
const handleChange = (event) => {
setValue(event.target.value);
onChange(event.target.value)
}
return (
<input
value={value}
type='text'
onChange={handleChange}>
</input>
)
}
なぜ lint なのでしょうか? 最初の例の lint ルールについて明確な説明はありますか?
それとも、ここでは使用しない方が良いのでしょうかuseEffect
? (私はフックの初心者です)
ベストアンサー1
onChange
リンター ルールをフックに含める理由useEffect
は、レンダリング間で変更される可能性がありonChange
、リンター ルールはそのような「古いデータ」の参照を防ぐことを目的としているためです。
例えば:
const MyParentComponent = () => {
const onChange = (value) => { console.log(value); }
return <MyCustomComponent onChange={onChange} />
}
の各レンダリングでは、MyParentComponent
異なるonChange
関数が に渡されますMyCustomComponent
。
onChange
あなたの特定のケースでは、おそらく気にする必要はないでしょう。関数が変更されたときではなく、値が変更されたときにのみ呼び出したいのですonChange
。しかし、 の使用方法からはそれが明らかではありませんuseEffect
。
ここでの根本は、your がuseEffect
やや慣用表現でないということです。
useEffect
は副作用に使用するのが最適ですが、ここでは「Y が変更されたら X を実行する」などの一種の「サブスクリプション」概念として使用しています。配列のメカニズムにより、機能的にはある程度機能しますがdeps
(ただし、この場合はonChange
初期レンダリングも呼び出しており、これはおそらく望ましくありません)、意図された目的ではありません。
を呼び出すことはonChange
、実際にはここでの副作用ではなく、onChange
のイベントをトリガーする効果にすぎません。したがって、 との両方を一緒に呼び出す 2 番目のバージョンの方が慣用的だ<input>
と思います。onChange
setValue
値を設定する他の方法(クリアボタンなど)がある場合、常に呼び出すことを覚えておく必要がonChange
あるのは面倒なので、次のように記述します。
const MyCustomComponent = ({onChange}) => {
const [value, _setValue] = useState('');
// Always call onChange when we set the new value
const setValue = (newVal) => {
onChange(newVal);
_setValue(newVal);
}
return (
<input value={value} type='text' onChange={e => setValue(e.target.value)}></input>
<button onClick={() => setValue("")}>Clear</button>
)
}
しかし、現時点ではこれは些細な問題です。