Some React applications use a dedicated “wrapper” component around a Context Provider to set up state for the Context. Doing so can help standardize setting up state for each usage of the Provider.
const ThemeContext = React.createContext();// Wrapper for ThemeContext that adds a friendly noticeconst ThemedMessage = ({ children, theme }) => {return (<ThemeContext.Provider value={theme}><p>This content is in {theme} mode!</p>{children}</ThemeContext.Provider>);};
React Context objects include a .Provider
property that is a React component. It takes in a value
prop to be made available to all its descendent components.
// Provides "hello world" as the MyContext value to descendants<MyContext.Provider value="hello world"><ChildComponent /></MyContext.Provider>
Descendents of a Context Provider may subscribe to the Provider’s data by passing the Context object to React’s useContext()
hook.
import MyContext from 'MyContext.js';const ConsumerComponent = () => {const contextValue = useContext(MyContext);// The component can then use contextValue}
The React.createContext()
function creates and returns a React Context object.
const CounterContext = React.createContext();
A Context’s .Provider
component may provide both a state value and its updater function via the value
prop.
const CounterContext = React.createContext();// Descendants of CounterArea will be able to update its count state by calling the `setCount` property provided by the CounterContext.Providerconst CounterArea = ({ children }) => {const [count, setCount] = useState(0);return (<CounterContext.Provider value={{ count, setCount }}>{children}</CounterContext.Provider>);};
Context is a feature of React that allows us to create a piece of state that any component within an area of your application can subscribe to.
Prop drilling is the term for when a piece of data is passed as a prop through a large number of components in a React application.
const App = () => {const [count, setCount] = useState(0);return <CounterContainer count={count} setCount={setCount} />}// This component drills props down to CounterDisplay and CounterButtonconst CounterContainer = ({count, setCount}) => {return (<><CounterDisplay count={count}/><CounterButton setCount={setCount}/></>)}const CounterDisplay = ({count}) => {return <h2>{count}</h2>}const CounterButton = ({setCount}) => {return <button setCount={setCount}>Increment</button>}
Downsides of prop drilling include components being harder to understand and excess rerenders of components that pass props without using them.
// This component prop drills three props: apple, banana, and cherryconst MyComponent = ({ apple, banana, cherry, children }) => {return (<ChildComponent apple={apple} banana={banana} cherry={cherry}>{children}</ChildComponent>);};
A .Provider
component can be used in multiple places in your application to provide different values for that subtree.
// The theme for App, Header, and Body will be "light". Only Footer will have the "dark" theme.<ThemeContext.Provider value="light"><App><Header /><Body /><ThemeContext.Provider value="dark"><Footer /></ThemeContext.Provider></App></ThemeContext.Provider>