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

use*_*640 8 reactjs react-hooks

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

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

Ret*_*sam 11

我个人建议传入上下文:我相信这将使自定义钩子更清晰、更灵活和更可测试。它将对上下文数据进行操作的逻辑与负责获取该数据的逻辑分离。

明晰

如果您useContext在自定义钩子内部使用,这将成为钩子的隐式约定:从调用签名中不清楚它取决于上下文中的值。一般来说,显式数据流优于隐式数据流。(当然,Context API 的存在是因为有时隐式数据流是有用的,但在大多数情况下我认为最好是显式的)

灵活性

您可能在某个时候发现一个组件需要利用自定义钩子中包含的逻辑,但需要提供与上下文中的值不同的值,或者可能想要修改该值。在这种情况下,这样做会非常方便:

const MySpecialCaseComponent = () => {
    const context = useContext(MyContext);
    useMyCustomHook({
       ...context,
       propToOverride: someValue
    });
    return (<div></div>)
}
Run Code Online (Sandbox Code Playgroud)

如果自定义钩子直接从上下文中读取,那将非常不方便——您可能不得不引入一个新组件,包装在一个新的上下文提供程序中。

可测试性

如果不依赖于上下文 API,则测试自定义钩子会更容易。也许在最简单的情况下,您可以使用测试数据调用自定义钩子并检查返回值。

或者你可以编写一个测试,如:

test("Test my custom hook", () => {
    const TestComponent = () => {
        useMyCustomHook({ /** test data */ });
        return (/* ... */);
    };
    const element = shallow(<TestComponent />);
    // do testing here
})
Run Code Online (Sandbox Code Playgroud)

如果您在钩子中使用上下文,那么您必须在提供程序中呈现您的测试组件<MyContext>,这会使事情变得更加复杂。 尤其是当您尝试进行浅层渲染时(更是如此,如果您正在使用react-test-renderer/shallow使用上下文测试组件会更加复杂


TL; DR我不认为这是错误的,以useContext自定义的钩子里,但我想明确的数据流量应该是你的第一个度假胜地,为所有常见的原因,明确的数据流通常优于隐式数据流。

  • 一些好的观点。在自定义挂钩中调用 useContext 的最大好处是,它使组件看起来更干净、更简洁。也就是说,我同意你的明确观点,并且我可能会遵循你的建议。 (4认同)
  • 另一件没有考虑到的事情是:当然,不将 useContext 放入钩子中意味着您可以在不依赖 useContext 的情况下进行测试;但是如果您将 useContext 放入您的钩子中,那么您的组件将不依赖于 useContext。问题在于您希望在哪里使用 useContext 依赖项来进行测试;你必须在某个地方嘲笑它。 (2认同)