1. ホーム
  2. reactjs

[解決済み] React Hooksの「exhaustive-deps」lintルールを理解する

2022-03-02 02:33:01

質問内容

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>
    )
} 

を追加する必要があるのです。 onChangeuseEffect の依存関係の配列です。しかし、私の理解では 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 ここで?(私はフックの初心者です。)

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

リンタールールが求める理由 onChange に入るようにします。 useEffect フックは onChange はレンダー間で変更されるため、lint ルールはそのような "古いデータ" 参照を防ぐことを目的としています。

例えば、以下のようなものです。

const MyParentComponent = () => {
    const onChange = (value) => { console.log(value); }

    return <MyCustomComponent onChange={onChange} />
}

のすべてのレンダリングは MyParentComponent を渡すと、異なる onChange 関数から MyCustomComponent .

この場合、おそらく気にすることはないでしょう。 onChange が変更されたときではなく、値が変更されたときに onChange 関数が変更されます。 しかし、あなたが使っている useEffect .


ここでの根本は、あなたの useEffect は、やや非idiomaticです。

useEffect は副作用のために使うのがベストですが、ここでは「Yが変化したらXを実行する」というように、一種のサブスクリプションの概念として使っています。 というように、ある種のサブスクリプションの概念として使用しています。 deps という配列があります(ただし、この場合は onChange は、最初のレンダリングで、おそらく不要なものです)しかし、これは意図した目的ではありません。

呼び出し onChange をトリガーすることによる効果にすぎません。 onChange イベント <input> . ということで、2つ目のバージョンでは onChangesetValue を一緒に使うのがよりイディオム的です。

もし、他に値を設定する方法(例えば、クリアボタン)があれば、常に 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>
    )
}

しかし、この時点ではこれは毛嫌いされる。