Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the scope of React Context?

Tags:

reactjs

I am not clear on where Context can be created in a React app. Can I create context anywhere in the component tree, and if so, is that context only scoped to children of where it is created? Or is Context inherently global?

Where in the documentation can I find this?

Case: I'm reusing a component multiple times on a page and would like to use context to handle data for sub-components, but that context needs to be unique to each sub-tree.

like image 505
Trees4theForest Avatar asked Jul 03 '20 02:07

Trees4theForest


Video Answer


2 Answers

There are 2 separate things: The context object, and the context provider.

The context object is created once globally (with an optional default value, which is global if no provider was passed from a component parent):

const FontContext = createContext('Courier');

While a context provider actually passes down its own local override of the context, which only applies to its children:

<FontContext.Provider value='Consolas'>
  {children}
</FontContext.Provider>

The interesting part is that contexts cascade:

<>
  <MyFontConsumer /> // value is 'Courier', the default
  <FontContext.Provider value='Consolas'>
    <MyFontConsumer /> // value is 'Consolas'
    <FontContext.Provider value='TimesRoman'>
      <MyFontConsumer /> // value is 'TimesRoman'
    </FontContext.Provider>
    <MyFontConsumer /> // value is 'Consolas'
  </FontContext.Provider>
</>

To consume the context in your component you can use the useContext() hook, (you can use the special <FontContext.Consumer> component or MyClassComponent.contextType instead) which requires you to pass the same object.

My preferred way to avoid having to pass around the context object is to keep them all in the same component and export a custom hook:


const FontContext = createContext('Courier')

export function FontProvider({value, children}) {
  return <FontContext.Provider value={value}>
    {children}
  </FontContext.Provider>
}

export function useFont() {
  return useContext(FontContext)
}

Now you can use it in your component:

import {FontProvider, useFont} from './FontProvider'

function App() {
  const font = useFont() // value is 'Courier', the default

   return <FontProvider value='TimesRoman'>
      <MyChild />
   </FontProvider>
}

function MyChild() {
  const font = useFont() // value is 'TimesRoman'
  ...
}
like image 164
Mordechai Avatar answered Oct 02 '22 15:10

Mordechai


I am not clear on where Context can be created in a React app. Can I create context anywhere in the component tree?

A context object can technically be created anywhere with createContext, but to actually set the value to something other than the default you need a provider component. The context will be available via its consumer or the useContext hook in any child components of the provider.

Is that context only scoped to children of where it is created?

If by "created" you mean where the provider is located, yes. However with the new context API you can set a default value, even without a provider.

Or is Context inherently global?

No not inherently, though contexts are often placed within or above the app's root component to become global for all practical purposes.

Where in the documentation can I find this?

  • Context
  • useContext hook

Case: I'm reusing a component multiple times on a page and would like to use context to handle data for sub-components, but that context needs to be unique to each sub-tree.

As far as I understand, you have two options here:

  1. Use a single context with different providers overriding it in sub-trees
  2. Have a different context for each sub-tree
like image 25
Nick McCurdy Avatar answered Oct 02 '22 15:10

Nick McCurdy