text: It is common in React for data to flow from top-to-bottom through props (parent component to children components), but this is not ideal all the time. There may be situations where you have data that needs to be available to many nested components at varying depths and passing props becomes difficult to maintain and error-prone.
  In this situation, it may seem like a good idea to use Redux to manage state, but many argue it should not be your first option.
  React Context is an alternative solution to sharing data across components, without having to pass props down manually at every level.
  In this article, you will explore the Context API and learn how it can be used to manage user state.
  To follow along with this article, you will need:
  This tutorial was verified with Node v15.3.0,
  npm v6.14.9, and
  react v17.0.1.
  Here’s an example of a
  Page component passing a
  user and
  avatarSize prop:
  <Page user={user} avatarSize={avatarSize} />
  Which renders a
  PageLayout component:
  <PageLayout user={user} avatarSize={avatarSize} />
  Which renders a
  NavigationBar component:
  <NavigationBar user={user} avatarSize={avatarSize} />
  Which renders a
  Link and
  Avatar that uses the
  user and
  avatarSize props:
  <Link href={user.permalink}> <Avatar user={user} size={avatarSize} /> </Link>
  In the above example, only the
  Avatar component actually uses the
  user prop. However each of its ancestor components (parent, grandparent, etc.) receives
  user and passes it down. This means that if the
  Avatar component needed another prop in the future, you would have to ensure that each of its ancestor components receives and passes it down.
  In reality, the
  user state will need to be shared across many different components, therefore passing it as a prop will result in it in nesting even deeper than the above example.
  React.createContext
  The
  React.createContext method returns a
  Context object. This
  Context object comes with two important React components that allow for subscribing to data:
  Provider and
  Consumer.
  When React renders a component that subscribes to this
  Context object it will read the current context value from the closest matching
  Provider component above it in the tree.
  The
  createContext method takes in an optional
  defaultValue argument, which is provided to
  Context.Consumer if a matching
  Context.Provider component could not be found in the tree.
  Create a
  Context object and export it to be used by other components:
  import React from 'react'; const userContext = React.createContext({user: {}}); export { userContext };
  In the example above, you initialized
  userContext and provided
  defaultValue of
  {user: {}}.
  Now that you have a
  Context object, you can provide it with a value and subscribe to changes.
  Context.Provider
  Pass user state as value to
  context.Provider so it can be consumed by
  context.Consumer:
  import React from 'react'; import Main from './Main'; import {userContext} from './userContext'; class App extends React.Component { constructor(props) { super(props); this.state = { user: {} }; } componentDidMount() { // get and set currently logged in user to state } render() { return ( <userContext.Provider value={this.state.user}> <Main/> </userContext.Provider> ); } } export default App;
  This is great to start with, wrapping the
  Main component with
  userContext.Provider ensures that the value you pass can be consumed within any of
  Main’s descendant child components.
  Context.Consumer
  userContext.Consumer takes in a function as a child. This function receives the current context value (value that is passed as a prop to
  userContext.Provider) and returns a React node.
  import Sidebar from './Sidebar'; import Content from './Content'; import Avatar from './Avatar'; import {userContext} from './userContext'; function Main(props) { return ( <Sidebar/> <userContext.Consumer> {({value}) => { <Avatar value={value}/> }} </userContext.Consumer> <Content/> ) } export default Main;
  In this case, it receives the
  App component’s
  state.user as a value and renders an
  Avatar component.
  Up to this point, you have used React Context to pass data to components that need it without having to manually pass props. Next, you will need to be able to update the context from a nested child component.
  Consider a button for logging a user out.
  In this case, you can pass a function down through the same context to allow consumers to update the context.
  import React from 'react'; import Main from './Main'; import {userContext} from './userContext'; class App extends React.Component { constructor(props) { super(props); this.state = { user: {} }; this.logout = this.logout.bind(this); } logout() { this.setState({user: {}}); } componentDidMount() { // get and set currently logged in user to state } render() { const value = { user: this.state.user, logoutUser: this.logout } return ( <userContext.Provider value={value}> <Main/> </userContext.Provider> ); } } export default App;
  The function that is passed to update context can be used in any nested component within the
  userContext.Provider component.
  import Sidebar from './Sidebar'; import Content from './Content'; import Avatar from './Avatar'; import LogoutButton from './LogoutButton'; import {userContext} from './userContext'; function Main(props) { return ( <Sidebar/> <userContext.Consumer> {({user, logoutUser}) => { return ( <Avatar user={user}/> <LogoutButton onClick={logoutUser}/> ); }} </userContext.Consumer> <Content/> ) } export default Main;
  The logout button has been added to the
  Main component.
  And that concludes an example of how to use React’s Context API to manage user state.
  In this article, you were introduced to React Context and using
  Context.Producer and
  Context.Consumer.
  If you’d like to learn more about React, take a look at our How To Code in React.js series, or check out our React