reactjs 如何在useEffect中跟踪对象引用?

3phpmpom  于 2023-04-20  发布在  React
关注(0)|答案(1)|浏览(190)

我正在构建一些API钩子,我遇到了deps属性的问题。我想在deps的内容更改时重新调用useEffect,而不是在永久循环中运行。deps可以是未定义的或any[]

export const useReader = <TResponseData>({ url, deps, options }: TypeUseReader<TResponseData>) => {
    const [data, setData] = useState<TResponseData | null>(null);
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const [error, setError] = useState<number | null >(null);

    async function fetchData(newUrl?: string) {}

    useEffect(() => {
       // ..fetch
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [url, deps]); // HERE, deps are forever loop

    return {
        data,
        isLoading,
        error,
        fetchData
    };
};

这就是我如何使用它:

return useReader<FOO>(
        {
            url: 'URL_PLACEHOLDER',
            deps: [anything] /* FIXME: deps enters FOREVER LOOP */
        }
    );

我所尝试的:
[deps ?? []]...[deps ?? []]deps-所有这些都会创建永久循环

8aqjt8rx

8aqjt8rx1#

问题是,当您使用deps作为数组字面量调用useReader时,每次都会创建一个新数组,因此useEffect正确地检测到值的变化。
一般来说,有两种方法来处理这个问题。
你可以让调用者负责-在useReader接口中指定它接受一个unknown类型的dep值。如果调用者想要传递一个值数组,那么这些值应该是稳定的,例如。

const dep = useMemo(() => [val1, val2], [val1, val2]);
return useReader<FOO>(
        {
            url: 'URL_PLACEHOLDER',
            isSuspended: false,
            initialValue: foo,
            dep   /* only changes if val1 or val2 has changed */
        }
    );

更简单、更灵活的方法是接受一个deps数组(类型为unknown[]),并将数组的成员分布在传递给useEffect的其他依赖项之后:

useEffect(() => {
        if (!isSuspended) {
            fetchData();
        }
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [isSuspended, url, ...(deps ?? [])]);

各种短绒对此感到不安,但就钩机械而言,这不是问题。

相关问题