【发布时间】:2021-06-16 08:04:19
【问题描述】:
让我们假设一个组件:
const Foo = ({id, onError}) => {
useEffect(() => {
subscribe(id).catch(error => onError(error));
return () => cleanup(id);
}, [id, onError]);
return <div>...</div>;
}
这个想法很简单——运行一个使用当前“id”订阅的效果。如果订阅失败,则调用一个事件处理程序onError,该处理程序作为道具向下传递。
但是,要使其正常工作,传递下来的 onError 属性必须在引用上是稳定的。换句话说,如果我的组件的消费者尝试了以下操作,他们可能会遇到为每个渲染运行效果的问题:
const Parent = () => {
// handleError is recreated for each render, causing the effect to run each time
const handleError = error => {
console.log("error", error);
}
return <Foo id="test" onError={handleError} />
}
相反,他们需要执行以下操作:
const Parent = () => {
// handleError identity is stable
const handleError = useCallback(error => {
console.log("error", error);
},[]);
return <Foo id="test" onError={handleError} />
}
这有效,但我对它有点不满意。 Foo 的消费者需要意识到 onError 必须是稳定的,除非您查看其底层实现,否则这不是显而易见的。它破坏了组件封装,消费者很容易在不知不觉中遇到问题。
是否有更好的模式来管理可以在useEffect 中调用的事件处理程序等道具?
【问题讨论】:
-
您确定组件上的
onError事件处理程序是处理来自subscribe的错误的正确位置。我会尝试让订阅处理它自己的错误。在这种情况下,您希望处理什么样的错误? -
@HåkenLid 假设
Foo是一个可重用的组件,每个消费者可能以不同的方式处理错误。它不一定是onError,它可以是任何事件(onSubscribed、onDataReceived等)。我只是想举一个简单的例子。
标签: reactjs react-hooks