I would suggest passing the context in, personally: I believe that will make the custom hook more clear, more flexible and more testable. It decouples the logic that operates on the context data from the logic responsible for getting that data.
Clarity
If you use useContext
inside a custom hook, that becomes an implicit contract for the hook: it's not clear from looking at the call signature that it depends on values from context. Explicit data flow is better than implicit data flow, generally. (Of course, the Context API exists because sometimes implicit data flow is useful, but in most cases I think it's better to be explicit)
Flexibility
You might at some point find a component that needs to leverage the logic contained in the custom hook, but needs to provide a different value than the one on the context, or perhaps wants to modify the value. In this case, it'd be very convenient to do this:
const MySpecialCaseComponent = () => {
const context = useContext(MyContext);
useMyCustomHook({
...context,
propToOverride: someValue
});
return (<div></div>)
}
That's highly inconvenient if the custom hook reads straight from context - you'd probably have to introduce a new component, wrapped in a new context provider.
Testability
It's easier to test a custom hook if it doesn't depend on context API. Perhaps in the simplest cases, you can just call your custom hook with test data and check the return value.
Or you can write a test like:
test("Test my custom hook", () => {
const TestComponent = () => {
useMyCustomHook({ /** test data */ });
return (/* ... */);
};
const element = shallow(<TestComponent />);
// do testing here
})
If you use context in your hook, then you'd have to render your test component inside a <MyContext>
provider, and that makes things more complicated. Especially if you're trying to do shallow render (and even more so if you're using react-test-renderer/shallow
, testing components with context is more complicated.
TL;DR I don't think it's wrong to useContext
inside a custom hook, but I think explicit data flow should be your first resort, for all the usual reasons that explicit data flow is generally preferred over implicit data flow.