Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it better to pass context to a custom hook or call useContext inside the custom hook?

I have a growing number of custom hooks and many of them access the same react context via the useContext hook. In many components there is the need to use more than one of these custom hooks.

Is it better to call useContext once per component and pass the context into my custom hooks or is it better to call useContext within each custom hook? There may not be a right or wrong answer, but by "better" I mean is there a best practice? Does one approach make more sense than the other?

like image 204
user1843640 Avatar asked Mar 13 '19 17:03

user1843640


People also ask

Can I use useContext inside a custom hook?

Create the useContextInside of this custom hook, we'll be using the useContext hook, that allows us to access both the theme and the setTheme function outside of this file. If useContext fails to create a context, it'll return undefined because we forgot the wrap our App or component in a ThemeProvider.

What is the difference between useContext and context API?

The useContext is the React hook, used in context API to consume the context state or object. There are two options for getting the context object. We can get the context object from Context Consumer or useContext Hook. UseContext Hook is an exquisite, more excellent way to get the context object with less code.

Can I use custom hook inside another custom hook?

While custom React Hooks are just Javascript functions, we can actually use other hooks inside them.

What does the useContext hook return when called?

The hook returns the value of the context: value = useContext(Context) . The hook also makes sure to re-render the component when the context value changes.


1 Answers

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.

like image 120
Retsam Avatar answered Oct 23 '22 14:10

Retsam