useContext() 反应钩子没有返回正确的值

Aiw*_*tko 5 javascript reactjs react-hooks

我将我的 Home 组件包装在以下布局中:

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>
  );
};
Run Code Online (Sandbox Code Playgroud)

我想在我的 Home 组件中使用 useContext 钩子,但它返回一个空对象:

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

  return (
    <Layout>
       // content data goes here
    </Layout>
  );
};
Run Code Online (Sandbox Code Playgroud)

我怀疑这是因为我在包含上下文提供程序的 Layout 包装器之外定义了上下文变量,所以它回退到我定义的上下文的默认值(一个空对象)。但是,即使我在布局提供程序中控制台记录 useContext 钩子,它也会返回一个空对象:

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

  return (
    <Layout>
      {console.log(React.useContext(DataContext))}
    </Layout>
  );
};
Run Code Online (Sandbox Code Playgroud)

知道为什么吗?

Tho*_*lle 7

useContext将获得valueProvider最靠近它的树。你Layout在里面Home,这将使Provider下面的它在树中。

你可以让Home一个孩子Layout去看看它的工作。

例子

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"));
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


Shu*_*tri 3

您关于 useContext 在布局之外使用时提供空对象的假设确实是正确的。如果层次结构中没有,Provider则 useContext 返回提供给的默认值React.createContext

此外,您只能React hooks在功能组件开始时使用,而不能在渲染中使用。因此,如果您像下面这样编写代码,您将能够正确记录上下文值

const Content: React.FunctionComponent = () => {
   const content = React.useContext(DataContext);
   console.log(content);
   return (
      <div>Content</div>
   )
}
const Home: React.FunctionComponent = () => {

  return (
    <Layout>
      <Content />
    </Layout>
  );
};
Run Code Online (Sandbox Code Playgroud)

工作演示