Context.Consumer vs useContext() to access values passed by Context.Provider
Asked Answered
G

2

64
<MyContext.Consumer>
    {value => { }}
</MyContext.Consumer>

VS

let value = useContext(MyContext);

What is the difference between this two snippets, using Context.Consumer and using useContext hook to access values passed by the context Provider? I think useContext will subscribe to the context Provider, since we passed the Context as an argument, so that it will trigger a re-render, when the provider value changes.

Gaslight answered 29/6, 2019 at 9:12 Comment(2)
Isn't first one is for Class component and 2nd one is for functional component ?Desultory
Is there any way we can skip both and have context value directly? I mean get it from createContextSigne
R
66

That is correct. They will do basically the same thing.

In my opinion, the useContext hook has a much nicer and readable syntax.

From React Docs:

https://reactjs.org/docs/hooks-reference.html#usecontext

useContext

const value = useContext(MyContext); Accepts a context object (the value returned from React.createContext) and returns the current context value for that context. The current context value is determined by the value prop of the nearest <MyContext.Provider> above the calling component in the tree.

When the nearest <MyContext.Provider> above the component updates, this Hook will trigger a rerender with the latest context value passed to that MyContext provider.

Also from React Docs:

https://reactjs.org/docs/context.html

Context.Consumer

<MyContext.Consumer>
 {value => /* render something based on the context value */}
</MyContext.Consumer>

A React component that subscribes to context changes. This lets you subscribe to a context within a function component.

UPDATE:

From: http://brianyang.com/react-hooks-a-deeper-dive-featuring-usecontext-and-usereducer/

From: https://testdriven.io/blog/react-hooks-advanced/

The new useContext hook to consume context does not change the concepts surrounding context, hence the plunge above. This context hook only gives us an extra, much prettier, way to consume context. It's amazingly helpful when applying it to components consuming multiple contexts.

Rosellaroselle answered 29/6, 2019 at 10:34 Comment(11)
Thanks. So if both subscribes to the context, what is the basic difference? Not regarding syntax.Gaslight
This article might help: I'll add it to the answer. brianyang.com/…Rosellaroselle
@Bastiat Isn't first one is for Class component and 2nd one is for functional component ?Desultory
@Desultory yes and no, you need to use Context.consumer with class components because you cannot use a hook inside a class component. However, the consumer simply passes values to the function, as you see in the example above, but the Consumer component doesnt know or care what is returned from that function. it could return class or functional components. In the end, it's just handing out values. As mentioned though, Hooks tend to me much cleaner especially if you have multiple providers.Shope
@Shope ` it will only rerender when those selected items change. . Component always re-rendered even if we use Context.Consumer`, please check codesandbox.io/s/lpk7xrwnmm?file=/src/App.js.Gaslight
@Shope – That is wrong. Both useContext and Context.Consumer will trigger a re-render when any item in the context is changed.Switchboard
The last link is broken. Correct link: testdriven.io/blog/react-hooks-advanced (which is also the original source of that article, see WBM).Almallah
@FabianIwand thanks! I've updated the link in the answer.Rosellaroselle
@Switchboard actually it's correct: codesandbox.io/p/devbox/hardcore-gates-7m2z2m. useContext will cause the component it is used within to completely rerender. Context.Consumer does not cause the component it is inside to renrender; It allows you to create adhoc views within components to where you're comfortable with that re-rendering occuring. You can of course achieve the same thing by simply splitting up your components into smaller parts and moving useContext to where it's best suited.Parsons
I'm confused by my own comment haha... is it possible I replied to a comment that doesn't exist anymore? In any case, @Parsons you are right that "Context.Consumer does not cause the component it is inside to renrender". I believe what I meant is that it would, itself, re-render.Switchboard
@Switchboard yeah. Just wanted to clear up any potential ambiguity. I think the React team are calling Context.Consumer old so they can delete code from react in future. This way we only have one way of doing a thing.Parsons
D
0

I have another way to think of the difference between the two based on the usecases. If I have a <Context.Provider> as a parent element within another component but I need to use a value within the Context towards the child element, then I would not be able to get the scope of useContext hook right there. Because the component we are in is not within Provider so obviously we need to create a <Context.Consumer> as the child element's wrapper and get the context value.

const CurrentComponent = () => {
     const { contextValue } = useContext("CreatedContext"); // We cannot use this
     return (
           <ParentElement>
             <Context.Provider>
                <ChildElement>
                   <Context.Consumer>
                      {({contextValue}) => {
                         <InnerElement prop={contextValue}/>
                      }}
                   </Context.Consumer>
                </ChildElement>
             </Context.Provider>
           </ParentElement>
     )
}
Drumbeat answered 20/10, 2023 at 9:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.