了解 React Hooks 'exhaustive-deps' lint 规则 [英] Understanding the React Hooks 'exhaustive-deps' lint rule

查看:109
本文介绍了了解 React Hooks 'exhaustive-deps' lint 规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解 'exhaustive-deps' lint 规则.

I'm having a hard time understanding the 'exhaustive-deps' lint rule.

我已经阅读了这篇文章这篇文章,但我找不到答案.

I already read this post and this post but I could not find an answer.

这是一个带有 lint 问题的简单 React 组件:

Here is a simple React component with the lint issue:

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 永远不会改变,所以它不应该在那里.

It requires me to add onChange to the useEffect dependencies array. But in my understanding onChange will never change, so it should not be there.

通常我是这样管理的:

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 规则有什么明确的解释吗?

Why the lint? Any clear explanation about the lint rule for the first example?

或者我不应该在这里使用 useEffect 吗?(我是一个有钩子的菜鸟)

Or should I not be using useEffect here? (I'm a noob with hooks)

推荐答案

linter 规则希望 onChange 进入 useEffect 钩子的原因是因为 onChange 以在渲染之间进行更改,并且 lint 规则旨在防止这种陈旧数据"引用.

The reason the linter rule wants onChange to go into the useEffect hook is because it's possible for onChange to change between renders, and the lint rule is intended to prevent that sort of "stale data" reference.

例如:

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

    return <MyCustomComponent onChange={onChange} />
}

MyParentComponent 的每次渲染都会将不同的 onChange 函数传递给 MyCustomComponent.

Every single render of MyParentComponent will pass a different onChange function to MyCustomComponent.

在您的特定情况下,您可能并不关心:您只想在值更改时调用 onChange,而不是在 onChange 函数更改时调用.但是,从您如何使用 useEffect 来看,这并不清楚.

In your specific case, you probably don't care: you only want to call onChange when the value changes, not when the onChange function changes. However, that's not clear from how you're using useEffect.

这里的根源在于您的 useEffect 有点单调.

The root here is that your useEffect is somewhat unidiomatic.

useEffect 最适合用于副作用,但在这里您将其用作一种订阅"概念,例如:当 Y 更改时执行 X".由于 deps 数组的机制,这确实在功能上起作用(尽管在这种情况下,您还在初始渲染时调用了 onChange,这可能是不需要的),但这不是预期的目的.

useEffect is best used for side-effects, but here you're using it as a sort of "subscription" concept, like: "do X when Y changes". That does sort of work functionally, due to the mechanics of the deps array, (though in this case you're also calling onChange on initial render, which is probably unwanted), but it's not the intended purpose.

调用 onChange 在这里真的不是副作用,它只是触发 onChange 事件的效果.所以我确实认为你的第二个版本同时调用 onChangesetValue 更惯用.

Calling onChange really isn't a side-effect here, it's just an effect of triggering the onChange event for <input>. So I do think your second version that calls both onChange and setValue together is more idiomatic.

如果有其他设置值的方法(例如清除按钮),不断地记住调用 onChange 可能会很乏味,所以我可以这样写:

If there were other ways of setting the value (e.g. a clear button), constantly having to remember to call onChange might be tedious, so I might write this as:

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

但在这一点上这是令人毛骨悚然的.

But at this point this is hair-splitting.

这篇关于了解 React Hooks 'exhaustive-deps' lint 规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆