Movatterモバイル変換


[0]ホーム

URL:


Is this page useful?

useContext is a React Hook that lets you read and subscribe tocontext from your component.

constvalue =useContext(SomeContext)

Reference

useContext(SomeContext)

CalluseContext at the top level of your component to read and subscribe tocontext.

import{useContext}from'react';

functionMyComponent(){
consttheme =useContext(ThemeContext);
// ...

See more examples below.

Parameters

  • SomeContext: The context that you’ve previously created withcreateContext. The context itself does not hold the information, it only represents the kind of information you can provide or read from components.

Returns

useContext returns the context value for the calling component. It is determined as thevalue passed to the closestSomeContext above the calling component in the tree. If there is no such provider, then the returned value will be thedefaultValue you have passed tocreateContext for that context. The returned value is always up-to-date. React automatically re-renders components that read some context if it changes.

Caveats

  • useContext() call in a component is not affected by providers returned from thesame component. The corresponding<Context>needs to beabove the component doing theuseContext() call.
  • Reactautomatically re-renders all the children that use a particular context starting from the provider that receives a differentvalue. The previous and the next values are compared with theObject.is comparison. Skipping re-renders withmemo does not prevent the children receiving fresh context values.
  • If your build system produces duplicates modules in the output (which can happen with symlinks), this can break context. Passing something via context only works ifSomeContext that you use to provide context andSomeContext that you use to read it areexactly the same object, as determined by a=== comparison.

Usage

Passing data deeply into the tree

CalluseContext at the top level of your component to read and subscribe tocontext.

import{useContext}from'react';

functionButton(){
consttheme =useContext(ThemeContext);
// ...

useContext returns thecontext value for thecontext you passed. To determine the context value, React searches the component tree and findsthe closest context provider above for that particular context.

To pass context to aButton, wrap it or one of its parent components into the corresponding context provider:

functionMyPage(){
return(
<ThemeContextvalue="dark">
<Form/>
</ThemeContext>
);
}

functionForm(){
// ... renders buttons inside ...
}

It doesn’t matter how many layers of components there are between the provider and theButton. When aButtonanywhere inside ofForm callsuseContext(ThemeContext), it will receive"dark" as the value.

Pitfall

useContext() always looks for the closest providerabove the component that calls it. It searches upwards anddoes not consider providers in the component from which you’re callinguseContext().

Fork
import{createContext,useContext}from'react';constThemeContext =createContext(null);exportdefaultfunctionMyApp(){return(<ThemeContextvalue="dark"><Form/></ThemeContext>)}functionForm(){return(<Paneltitle="Welcome"><Button>Sign up</Button><Button>Log in</Button></Panel>);}functionPanel({title,children}){consttheme =useContext(ThemeContext);constclassName ='panel-' +theme;return(<sectionclassName={className}><h1>{title}</h1>{children}</section>)}functionButton({children}){consttheme =useContext(ThemeContext);constclassName ='button-' +theme;return(<buttonclassName={className}>{children}</button>);}

Updating data passed via context

Often, you’ll want the context to change over time. To update context, combine it withstate. Declare a state variable in the parent component, and pass the current state down as thecontext value to the provider.

functionMyPage(){
const[theme,setTheme] =useState('dark');
return(
<ThemeContextvalue={theme}>
<Form/>
<ButtononClick={()=>{
setTheme('light');
}}>
Switch to light theme
</Button>
</ThemeContext>
);
}

Now anyButton inside of the provider will receive the currenttheme value. If you callsetTheme to update thetheme value that you pass to the provider, allButton components will re-render with the new'light' value.

Examples of updating context

Example 1 of 5:
Updating a value via context

In this example, theMyApp component holds a state variable which is then passed to theThemeContext provider. Checking the “Dark mode” checkbox updates the state. Changing the provided value re-renders all the components using that context.

Fork
import{createContext,useContext,useState}from'react';constThemeContext =createContext(null);exportdefaultfunctionMyApp(){const[theme,setTheme] =useState('light');return(<ThemeContextvalue={theme}><Form/><label><inputtype="checkbox"checked={theme ==='dark'}onChange={(e)=>{setTheme(e.target.checked ?'dark' :'light')}}/>        Use dark mode</label></ThemeContext>)}functionForm({children}){return(<Paneltitle="Welcome"><Button>Sign up</Button><Button>Log in</Button></Panel>);}functionPanel({title,children}){consttheme =useContext(ThemeContext);constclassName ='panel-' +theme;return(<sectionclassName={className}><h1>{title}</h1>{children}</section>)}functionButton({children}){consttheme =useContext(ThemeContext);constclassName ='button-' +theme;return(<buttonclassName={className}>{children}</button>);}

Note thatvalue="dark" passes the"dark" string, butvalue={theme} passes the value of the JavaScripttheme variable withJSX curly braces. Curly braces also let you pass context values that aren’t strings.


Specifying a fallback default value

If React can’t find any providers of that particularcontext in the parent tree, the context value returned byuseContext() will be equal to thedefault value that you specified when youcreated that context:

constThemeContext =createContext(null);

The default valuenever changes. If you want to update context, use it with state asdescribed above.

Often, instead ofnull, there is some more meaningful value you can use as a default, for example:

constThemeContext =createContext('light');

This way, if you accidentally render some component without a corresponding provider, it won’t break. This also helps your components work well in a test environment without setting up a lot of providers in the tests.

In the example below, the “Toggle theme” button is always light because it’soutside any theme context provider and the default context theme value is'light'. Try editing the default theme to be'dark'.

Fork
import{createContext,useContext,useState}from'react';constThemeContext =createContext('light');exportdefaultfunctionMyApp(){const[theme,setTheme] =useState('light');return(<><ThemeContextvalue={theme}><Form/></ThemeContext><ButtononClick={()=>{setTheme(theme ==='dark' ?'light' :'dark');}}>        Toggle theme</Button></>)}functionForm({children}){return(<Paneltitle="Welcome"><Button>Sign up</Button><Button>Log in</Button></Panel>);}functionPanel({title,children}){consttheme =useContext(ThemeContext);constclassName ='panel-' +theme;return(<sectionclassName={className}><h1>{title}</h1>{children}</section>)}functionButton({children,onClick}){consttheme =useContext(ThemeContext);constclassName ='button-' +theme;return(<buttonclassName={className}onClick={onClick}>{children}</button>);}

Overriding context for a part of the tree

You can override the context for a part of the tree by wrapping that part in a provider with a different value.

<ThemeContextvalue="dark">
...
<ThemeContextvalue="light">
<Footer/>
</ThemeContext>
...
</ThemeContext>

You can nest and override providers as many times as you need.

Examples of overriding context

Example 1 of 2:
Overriding a theme

Here, the buttoninside theFooter receives a different context value ("light") than the buttons outside ("dark").

Fork
import{createContext,useContext}from'react';constThemeContext =createContext(null);exportdefaultfunctionMyApp(){return(<ThemeContextvalue="dark"><Form/></ThemeContext>)}functionForm(){return(<Paneltitle="Welcome"><Button>Sign up</Button><Button>Log in</Button><ThemeContextvalue="light"><Footer/></ThemeContext></Panel>);}functionFooter(){return(<footer><Button>Settings</Button></footer>);}functionPanel({title,children}){consttheme =useContext(ThemeContext);constclassName ='panel-' +theme;return(<sectionclassName={className}>{title &&<h1>{title}</h1>}{children}</section>)}functionButton({children}){consttheme =useContext(ThemeContext);constclassName ='button-' +theme;return(<buttonclassName={className}>{children}</button>);}

Optimizing re-renders when passing objects and functions

You can pass any values via context, including objects and functions.

functionMyApp(){
const[currentUser,setCurrentUser] =useState(null);

functionlogin(response){
storeCredentials(response.credentials);
setCurrentUser(response.user);
}

return(
<AuthContextvalue={{ currentUser, login }}>
<Page/>
</AuthContext>
);
}

Here, thecontext value is a JavaScript object with two properties, one of which is a function. WheneverMyApp re-renders (for example, on a route update), this will be adifferent object pointing at adifferent function, so React will also have to re-render all components deep in the tree that calluseContext(AuthContext).

In smaller apps, this is not a problem. However, there is no need to re-render them if the underlying data, likecurrentUser, has not changed. To help React take advantage of that fact, you may wrap thelogin function withuseCallback and wrap the object creation intouseMemo. This is a performance optimization:

import{useCallback,useMemo}from'react';

functionMyApp(){
const[currentUser,setCurrentUser] =useState(null);

constlogin =useCallback((response)=>{
storeCredentials(response.credentials);
setCurrentUser(response.user);
},[]);

constcontextValue =useMemo(()=>({
currentUser,
login
}),[currentUser,login]);

return(
<AuthContextvalue={contextValue}>
<Page/>
</AuthContext>
);
}

As a result of this change, even ifMyApp needs to re-render, the components callinguseContext(AuthContext) won’t need to re-render unlesscurrentUser has changed.

Read more aboutuseMemo anduseCallback.


Troubleshooting

My component doesn’t see the value from my provider

There are a few common ways that this can happen:

  1. You’re rendering<SomeContext> in the same component (or below) as where you’re callinguseContext(). Move<SomeContext>above and outside the component callinguseContext().
  2. You may have forgotten to wrap your component with<SomeContext>, or you might have put it in a different part of the tree than you thought. Check whether the hierarchy is right usingReact DevTools.
  3. You might be running into some build issue with your tooling that causesSomeContext as seen from the providing component andSomeContext as seen by the reading component to be two different objects. This can happen if you use symlinks, for example. You can verify this by assigning them to globals likewindow.SomeContext1 andwindow.SomeContext2 and then checking whetherwindow.SomeContext1 === window.SomeContext2 in the console. If they’re not the same, fix that issue on the build tool level.

I am always gettingundefined from my context although the default value is different

You might have a provider without avalue in the tree:

// 🚩 Doesn't work: no value prop
<ThemeContext>
<Button/>
</ThemeContext>

If you forget to specifyvalue, it’s like passingvalue={undefined}.

You may have also mistakingly used a different prop name by mistake:

// 🚩 Doesn't work: prop should be called "value"
<ThemeContexttheme={theme}>
<Button/>
</ThemeContext>

In both of these cases you should see a warning from React in the console. To fix them, call the propvalue:

// ✅ Passing the value prop
<ThemeContextvalue={theme}>
<Button/>
</ThemeContext>

Note that thedefault value from yourcreateContext(defaultValue) call is only usedif there is no matching provider above at all. If there is a<SomeContext value={undefined}> component somewhere in the parent tree, the component callinguseContext(SomeContext)will receiveundefined as the context value.



[8]ページ先頭

©2009-2025 Movatter.jp