reactjs 当依赖项使用相同的对象值更改时,阻止useEffect运行

gab6jxml  于 2023-04-11  发布在  React
关注(0)|答案(1)|浏览(143)

我一直在思考这个问题有一段时间了。我一直在和自己斗争,说"but this is how React works" vs "but most people don't know"
对于我正在编写的一个库,用户需要向钩子提供一个配置对象,然后库“同步”这个配置对象并返回结果。
理想(简化)情况:

const myHook = (configObjectProvidedByUser, onError) => {
    const [state, setState] = useState();

    useEffect(() => {
        let ignore = false;
        doSomeSyncing(configObjectProvidedByUser)
            .then((response) => {
                if (!ignore) {
                    setState({ source: configObjectProvidedByUser, resolved: response });
                }
            })
            .catch((error) => {
                if (!ignore) {
                    setState({ source: configObjectProvidedByUser, error });
                    onError(error);
                }
            });

        return () => {
            ignore = true;
        };
    }, [configObjectProvidedByUser, onError]);

    if (configObjectProvidedByUser === state?.source) {
        return state;
    }
    return undefined;
};

这段代码按预期工作。但只有当实现者不每次都提供新的configObjectProvidedByUser时。
实现者将编写以下代码:

// getSomeConfig returns a new object every time
myHook(getSomeConfig(), (error) => logError(error))

这会导致效果在每个渲染器上运行,因为一个新的对象被创建。我知道这是react的工作原理,我知道实现者可以使用useMemo来记忆getSomeConfig。但它也是一个像这样的真人程序。有什么方法可以防止这种编程风格吗?或者有人有任何其他关于如何处理这些情况的建议吗?
我想到的一个解决方案是使用lodash.isEqual来比较configObjectProvidedByUser。但是这会导致运行效果清理函数的问题,该函数仍然会被触发,忽略当前的异步操作。

czfnxgou

czfnxgou1#

我假设 “我想到的一个解决方案是使用lodash.isEqual来比较configObjectProvidedByUser。但是这会导致运行效果清理函数的问题,该函数仍然会被触发,忽略当前的异步操作。" 你的意思是在useEffect钩子内的IF语句中比较传入的配置值?
解决这个问题的一个方法是不要求useEffect钩子比较对象,而是要求它比较一个字符串值,如下所示:https://codepen.io/crooy/pen/abRzoBd
免责声明:这里有一个计算代价,JSON.stringify也有问题,因为它不能确保字段的顺序相同。

  • 回复编辑 *:如果config对象中也有函数,比如onError,怎么办?

在这种情况下,除了Typescript中的一些强类型和良好的文档之外,没有什么可以保存你。还有另一种选择......也许有点不正统,你可以让钩子返回一个Subscribable/Observable/EventTarget示例。然而,我猜这只是 “just dont do that” 的变体😅。

相关问题