我有越来越多的自定义钩子,其中许多通过useContext
钩子访问相同的反应上下文。 在许多组件中,需要使用多个这些自定义钩子。
是每个组件调用useContext
一次并将上下文传递到我的自定义钩子中更好,还是在每个自定义钩子中调用useContext
更好? 可能没有正确或错误的答案,但我所说的"更好"是指是否有最佳实践?一种方法比另一种方法更有意义吗?
我个人建议传递上下文: 我相信这将使自定义钩子更清晰、更灵活、更易于测试。 它将对上下文数据进行操作的逻辑与负责获取该数据的逻辑分离。
清晰
如果在自定义钩子中使用useContext
,这将成为钩子的隐式协定:查看调用签名并不清楚它是否依赖于上下文中的值。 通常,显式数据流优于隐式数据流。 (当然,上下文 API 的存在是因为有时隐式数据流很有用,但在大多数情况下,我认为最好是明确的)
灵活性
在某些时候,您可能会发现一个组件需要利用自定义挂钩中包含的逻辑,但需要提供与上下文中的值不同的值,或者可能想要修改该值。 在这种情况下,这样做会非常方便:
const MySpecialCaseComponent = () => {
const context = useContext(MyContext);
useMyCustomHook({
...context,
propToOverride: someValue
});
return (<div></div>)
}
如果自定义钩子直接从上下文读取,这将非常不方便 - 您可能必须引入一个新的组件,包装在新的上下文提供程序中。
测试
如果自定义挂钩不依赖于上下文 API,则测试它更容易。 也许在最简单的情况下,您可以使用测试数据调用自定义钩子并检查返回值。
或者你可以编写一个测试,比如:
test("Test my custom hook", () => {
const TestComponent = () => {
useMyCustomHook({ /** test data */ });
return (/* ... */);
};
const element = shallow(<TestComponent />);
// do testing here
})
如果在钩子中使用上下文,则必须在<MyContext>
提供程序中呈现测试组件,这使事情变得更加复杂。特别是如果你试图做浅表渲染(如果你使用react-test-renderer/shallow
更是如此,使用上下文测试组件会更加复杂。
TL;DR我不认为在自定义钩子中useContext
是错误的,但我认为显式数据流应该是您的第一手段,出于所有常见原因,显式数据流通常优于隐式数据流。