设计React Hooks可以防止react-hooks/exhaustive-deps警告 [英] Designing React Hooks prevent react-hooks/exhaustive-deps warning

查看:2327
本文介绍了设计React Hooks可以防止react-hooks/exhaustive-deps警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一个挂钩,以便仅在挂钩依赖项更改时才获取数据. 它可以按预期运行,但我收到了棉绒警告:

I am designing a hook to fetch data only when the hooks dependencies change. It works as expected but I receive the linter warnings:

React Hook useEffect was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies.

React Hook useEffect has missing dependencies: 'data', 'errorHandler', 'route', and 'successHandler'. Either include them or remove the dependency array. If 'successHandler' changes too often, find the parent component that defines it and wrap that definition in useCallback. 

据我所知,我不希望所有这些var都存在于我的依赖项中,因为我不想在这些更改时触发此钩子,我只想在我通过的依赖项更改时触发它.

As far as I am aware I do not want all these vars in my dependencies as I don't want to fire this hook when these change, I only want to fire it when the dependencies I pass change.

问题: 如何以一种与钩子短绒标准一致的方式设计useFetch()钩子(如果我的设计模式不符合标准,请详细说明应如何做到最好).

Question: How can I design useFetch() hook in a way that coincides with the hooks linter standards (if my design pattern is not up to par, please elaborate on how best this should be accomplished).

我的useFetch()钩子

function useFetch(
    {
        route,
        data = {},
        successHandler,
        errorHandler,
    },
    dependencies = []) {
    const [loading, setLoading] = useState(true);
    useEffect(() => {
        setLoading(true);
        postJson({route}, data)
            .then(
                res => {
                    if(isFunction(successHandler)) successHandler(res);
                },
                ({responseJSON: err}) => {
                    if(isFunction(errorHandler)) {
                        errorHandler(err);
                    } else {
                        notify({text: err.message || messages.saveFailed(), cssClass: 'error'});
                    }
                }
            )
            .finally(() => {
                setLoading(false);
            });
    }, dependencies);
    return loading;
}

使用useFetch()

function MyComponent({data, selectedReviewId, setField}) {
    const loading = useFetch({
        route: 'foo.fetchData',
        data: {crrType, clientId, programId, userId},
        successHandler: d => setField([], d) // setField() will set data with the value fetched in useFetch() 
    }, [selectedReviewId]);

    return loading ? <SpinnerComponent/> : <div>{data.foo}</div>;
}

推荐答案

您已经将依赖项作为数组传递了,但是在接收端,它实际上是指向数组的单个变量. useEffect()的Lint规则要求您像下面的代码中那样在方括号中传递依赖项.

You have passed dependency as array but on the receiving end, it's essentially a single variable pointing to an array. Lint rule of useEffect() requires that you pass dependencies in square brackets like done in following code.

现在有一些技术资料.记住产生警告的原因.皮棉语法地检查代码.它没有涉及语义.从语义上讲,您的依赖项列表是正确的,因为您要传递数组,但是从语法上讲,它不是作为数组传递的,即它是一个未在方括号中传递的单个变量(例如[dependencies])(这是lint正在寻找的东西) ).因此,为了满足皮棉的要求,您应该编写:

Now some technical stuff. Remember what's generating the warning. It's the lint which checks code syntactically. It doesn't go into semantics. Semantically, your list of dependencies is correct, as you are passing an array but syntactically, it's not being passed as an array i.e. it's a single variable not passed in square brackets (like this [dependencies]) (which is something lint is looking for). So in order to satisfy lint, you should write:

useEffect(
  () => { // implementation of function },
  [dependencies]
);

此外,当您发送依赖项数组时,还可以使用散布运算符,如下所示:

Further, as you are sending an array of dependencies, you can also use spread operator, like this:

useEffect(
  () => { // implementation of function },
  [...dependencies]
);

这将通过Babel transpiler将数组元素散布到array运算符中.皮棉也将保持安静.

This will spread the array elements inside array operator by Babel transpiler. Lint will also remain quiet.

这篇关于设计React Hooks可以防止react-hooks/exhaustive-deps警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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