将上下文传递给自定义钩子还是在自定义钩子内调用useContext更好?

时间:2019-03-13 17:01:42

标签: reactjs react-hooks

我的自定义钩子越来越多,其中许多通过useContext钩子访问相同的react上下文。在许多组件中,需要使用多个自定义钩子中的一个。

是否最好每个组件调用一次useContext并将上下文传递到我的自定义钩子中?还是最好在每个自定义钩子中调用useContext?可能没有正确或错误的答案,但“更好”是指有最佳实践吗?一种方法比另一种更有意义吗?

1 个答案:

答案 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/shallowtesting components with context is more complicated时更是如此。


TL; DR 我认为在自定义钩子中useContext错误,但我认为显式数据流应该是您的首选,由于所有通常的原因,显式数据流通常比隐式数据流更受欢迎。