设计React Hooks可以防止React-Hooks / Exhaustive-deps警告

时间:2019-09-18 01:05:07

标签: javascript reactjs functional-programming react-hooks

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

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,因为我不想在这些更改时触发此钩子,我只想在我通过的依赖项更改时触发它。

问题: 我该如何设计useFetch()钩子,使其与钩子短绒标准相吻合(如果我的设计模式不符合标准,请详细说明应如何做到最好)。

我的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>;
}

2 个答案:

答案 0 :(得分:2)

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

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

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

此外,在发送一系列依赖项时,您还可以使用扩展运算符,如下所示:

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

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

答案 1 :(得分:1)

eslint警告是正确的-您应将其作为依赖项。例如,在您的MyComponent中,如果data发生了变化,并且不在依赖列表中,则您的useEffect钩子将调用fetch将过期data

对其他人同样适用-建议将其添加到依赖项列表中。

对于第一个错误,虽然不是很理想,但可能是可以的。您有一个动态的依赖项列表-eslint无法确定您是否拥有所有必需的内容。

您的解决方案可能会起作用-但它非常脆弱。如果您的dependencies发生更改(例如,其他元素或已删除的元素)