我的 useContext 组件如何知道获取 App.js 中的值?

How does my useContext component know to get the value in App.js?

我正在学习教程,它看起来像这样:

App.js

import React from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Index } from './pages/index';
import { About } from './pages/about/about';
import { UserContext } from './UserContext';

function AppRouter() {
  return (
    <Router>
      <div>
    <nav>
      <ul>
        <li>
          <Link to='/'> Home</Link>
        </li>
        <li>
          <Link to='/about'>About</Link>
        </li>
      </ul>
    </nav>
    <UserContext.Provider value='hello from context'>
      <Route path='/' exact component={Index} />
      <Route path='/about/' component={About} />
    </UserContext.Provider>
      </div>
    </Router>
  );
}

export default AppRouter;

UserContext.js

import {createContext} from 'react'



export const UserContext = createContext(null);

index.js

import React, { useContext } from 'react';
import { UserContext } from '../UserContext';

export function Index() {
  const msg= useContext(UserContext);



  return (
    <div>
      <h2>Home</h2>;
      <div>{msg}</div>;
    </div>
  );
}

当我 运行 这个 React 应用程序时,{msg} 变成 App.js 文件中的 hello from context

我不明白的是,当我查看 index.js 时,它仅从 UserContext.js 导入,它怎么知道 valueApp.js 文件?在我看来,如果我还导入了 App.js 文件,它只会看到。但是 React 应用程序只知道在哪里可以找到它。答案是,当 index.js 导入 UserContext 时,应用程序会四处查看以查看从其他地方导入 UserContext.js,然后根据它看到的所有内容构建 React 应用程序的输出?我觉得我错过了很大一部分反应应用程序,这些应用程序会让我更清楚。

如果不揭开 React 框架、ReactDOM 和 Fiber 的面纱,可能最容易想到 React Context API as an optimized version of the Lifting State Up 模式。

并不是 React 正在抓取您所有的导入等来确定使用了哪些文件,而是在您编写所有文件时生成的 DOM(React 的 VirtualDOM)组成您的应用程序的组件。您使用 JSX 来描述 UI 结构。

我们将从举升状态示例开始。

const Child1 = ({ value }) => <div>{value}</div>;

const Child2 = ({ setValue }) => <button onClick={() => setValue(42)}>Update</button>;

const Parent = () => {
  const [value, setValue] = React.useState(0);
  return (
    <>
      <Child1 value={value} />
      <Child2 setValue={setValue} />
    </>
  );
};

这里我们有一个以 Parent 作为根节点和两个叶节点 Child1Child2 的树。请注意,Child1 不知道也不关心 value 来自哪里或如何更新,它只是接收一个 prop。同样,Child2 不知道也不关心什么正在消耗它正在更新的值。

我们会将状态提升一个级别并添加一个中间组件。

const IntermediateComponent1 = (props) => (
  <div>
    <h1>I'm an intermediate child component</h1>
    <Child1 value={props.value} />
  </div>
);

const IntermediateComponent2 = (props) => (
  <div>
    <h1>I'm another intermediate child component</h1>
    <Child2 setValue={props.setValue} />
  </div>
);

const Parent = () => {
  const [value, setValue] = React.useState(0);
  return (
    <>
      <IntermediateComponent1 value={value} />
      <IntermediateComponent2 setValue={setValue} />
    </>
  );
};

您现在应该注意到两件事:

  1. Child 1 和 2 相距较远,但一般的 DOM 结构允许数据从单个位置流出并被 children 更向下的树使用。
  2. 中间组件需要知道它们需要代理到其后代的道具(issue/pattern 称为“props-drilling”)。

React 上下文 API 是一种做同样事情的方法,但不需要显式传递 (drill) 道具通过所有中间 children .上下文提供者是根节点,它提供了一个值,供 children 在树的更下方使用。

const Child1 = () => {
  const { value } = useContext(MyContext); // <-- "value" out
  return <div>{value}</div>;
};

const Child2 = () => {
  const { setValue } = useContext(MyContext); // <-- "setValue" out
  return <button onClick={() => setValue(42)}>Update</button>
};

const IntermediateComponent1 = () => (
  <div>
    <h1>I'm an intermediate child component</h1>
    <Child1 />
  </div>
);

const IntermediateComponent2 = () => (
  <div>
    <h1>I'm another intermediate child component</h1>
    <Child2 />
  </div>
);

const Parent = () => {
  const [value, setValue] = React.useState(0);
  return (
    <MyContext.Provider value={{ value, setValue }}> // <-- "value" in
      <IntermediateComponent1 />
      <IntermediateComponent2 />
    </MyContext.Provider>
  );
};

现在,希望您可以了解后代如何通过生成的 DOM 树结构使用从上下文提供的值。使用上下文时,children 将访问最接近的上下文提供者的上下文值 以上 它们在树中。也就是说,最近的祖先 Provider 组件。