我的自定义钩子越来越多,其中许多通过useContext
钩子访问相同的react上下文。在许多组件中,需要使用多个自定义钩子中的一个。
是否最好每个组件调用一次useContext
并将上下文传递到我的自定义钩子中?还是最好在每个自定义钩子中调用useContext
?可能没有正确或错误的答案,但“更好”是指有最佳实践吗?一种方法比另一种更有意义吗?
答案 0 :(得分:3)
我建议亲自传递上下文:我相信这将使自定义钩子更加清晰,更灵活且更具可测试性。它将对上下文数据进行操作的逻辑与负责获取该数据的逻辑分离。
如果在自定义钩子中使用useContext
,将成为该钩子的隐式契约:从调用签名中看,它取决于上下文的值还不清楚。通常,显式数据流比隐式数据流好。 (当然,存在Context 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
,testing components with context is more complicated时更是如此。
TL; DR 我认为在自定义钩子中useContext
是错误,但我认为显式数据流应该是您的首选,由于所有通常的原因,显式数据流通常比隐式数据流更受欢迎。