Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useContext() react hook doesn't return the correct value

I wrap my Home component in the following layout:

export const DataContext = React.createContext({});

const Layout: React.FunctionComponent = (props) => {
  const data = {title: "abc", description: "def"};
  
  return (
    <DataContext.Provider value={data}>
        {props.children}
    </DataContext.Provider>
  );
};

I would like to use useContext hook in my Home component, but it returns an empty object:

const Home: React.FunctionComponent = () => {
  const content = React.useContext(DataContext);

  return (
    <Layout>
       // content data goes here
    </Layout>
  );
};

I suspected that this is because I define context variable outside of Layout wrapper, which contains context provider, so it falls back to the default value of the context that I defined (an empty object). However, even if I console log the useContext hook inside the layout provider, it also returns an empty object:

const Home: React.FunctionComponent = () => {
  const content = React.useContext(DataContext);

  return (
    <Layout>
      {console.log(React.useContext(DataContext))}
    </Layout>
  );
};

Any idea why?

like image 740
Aiwatko Avatar asked Feb 19 '19 18:02

Aiwatko


People also ask

What is react context in React React?

React Context is a way to manage state globally. It can be used together with the useState Hook to share state between deeply nested components more easily than with useState alone. State should be held by the highest parent component in the stack that requires access to the state.

How to add context to L1 component in react?

First step is to create a context object. For that, import createContext from React. Next, we create a context object. Here, "John" is the default value of the context. We can override the value when using the context object. We need to now provide the context to the L1 component. For that, wrap the L1 component inside NameContext.provider.

What is the use of defaultValue argument in react?

The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Note: passing undefined as a Provider value does not cause consuming components to use defaultValue. Use static context like following.


1 Answers

useContext will get the value from the Provider closest to it up the tree. Your Layout is inside Home, which will make the Provider below it in the tree.

You could make Home a child to Layout instead to see it working.

Example

const DataContext = React.createContext({});

const Layout = props => {
  const data = { title: "abc", description: "def" };

  return (
    <DataContext.Provider value={data}>{props.children}</DataContext.Provider>
  );
};

const Home = () => {
  const content = React.useContext(DataContext);

  return <div>{JSON.stringify(content)}</div>;
};

function App() {
  return (
    <Layout>
      <Home />
    </Layout>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
like image 98
Tholle Avatar answered Nov 14 '22 11:11

Tholle