我在React中看到的所有新上下文API示例都在一个文件中,例如https://github.com/wesbos/React-Context.

当我试图让它跨多个文件工作时,我显然遗漏了一些东西.

我希望制作一个GlobalConfiguration组件(下面MyProvider个)来创建和管理上下文中的值,为从中读取的任何子组件(下面MyConsumer个)做好准备.

应用程序.js

render() {
    return (
        <MyProvider>
            <MyConsumer />
        </MyProvider>
    );
}

供应商.js

import React, { Component } from 'react';

const MyContext = React.createContext('test');

export default class MyProvider extends Component {

    render() {
        return (
            <MyContext.Provider
                value={{ somevalue: 1 }}>
                {this.props.children}
            </MyContext.Provider >
        );
    }
}

消费者js

import React, { Component } from 'react';

const MyContext = React.createContext('test');

export default class MyConsumer extends Component {

    render() {

        return (
            <MyContext.Consumer>
                {(context) => (
                    <div>{context.state.somevalue}</div>
                )}
            </MyContext.Consumer>
        );
    }
}

不幸的是,这在控制台中失败:

消费者js:12 Uncaught TypeError: Cannot read property 'somevalue' of undefined

我完全没有抓住重点吗?是否有文档或示例说明这是如何跨多个文件工作的?

推荐答案

我认为你遇到的问题是,你正在创建两个不同的上下文,并试图将它们作为一个整体使用.React.createContext创建的Context连接着ProviderConsumer.

制作一个文件(我称之为配置上下文.js)

配置上下文.js

import React, { Component, createContext } from "react";

// Provider and Consumer are connected through their "parent" context
const { Provider, Consumer } = createContext();

// Provider will be exported wrapped in ConfigProvider component.
class ConfigProvider extends Component {
  state = {
    userLoggedIn: false,                            // Mock login
    profile: {                                      // Mock user data
      username: "Morgan",
      image: "https://morganfillman.space/200/200",
      bio: "I'm Mogran—so... yeah."
    },
    toggleLogin: () => {
      const setTo = !this.state.userLoggedIn;
      this.setState({ userLoggedIn: setTo });
    }
  };

  render() {
    return (
      <Provider
        value={{
          userLoggedIn: this.state.userLoggedIn,
          profile: this.state.profile,
          toggleLogin: this.state.toggleLogin
        }}
      >
        {this.props.children}
      </Provider>
    );
  }
}

export { ConfigProvider };

// I make this default since it will probably be exported most often.
export default Consumer;

指数js

...
// We only import the ConfigProvider, not the Context, Provider, or Consumer.
import { ConfigProvider } from "./configContext";
import Header from "./Header";
import Profile from "./Profile";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <ConfigProvider>
        <Header />
        <main>
          <Profile />
        </main>
        <footer>...</footer>
      </ConfigProvider>
    </div>
  );
}
...

头球.js

import React from 'react'
import LoginBtn from './LoginBtn'
... // a couple of styles
const Header = props => {
  return (
... // Opening tag, etc.
      <LoginBtn />  // LoginBtn has access to Context data, see file.
... // etc.
export default Header

登录.js

import React from "react";
import Consumer from "./configContext";

const LoginBtn = props => {
  return (
    <Consumer>
      {ctx => {
        return (
          <button className="login-btn" onClick={() => ctx.toggleLogin()}>
            {ctx.userLoggedIn ? "Logout" : "Login"}
          </button>
        );
      }}
    </Consumer>
  );
};

export default LoginBtn;

轮廓js

import React, { Fragment } from "react";
import Consumer from "./configContext"; // Always from that same file.

const UserProfile = props => {...}; // Dumb component

const Welcome = props => {...}; // Dumb component

const Profile = props => {
  return (
    <Consumer>
      ...
        {ctx.userLoggedIn ? (
          <UserProfile profile={ctx.profile} />
        ) : (<Welcome />)}
      ...
    </Consumer>
  ...

Reactjs相关问答推荐

我的组件在jsx文件中继续重新渲染

CreateBrowserRouter将props 传递给父组件以验证权限

react 挂钩-使用有效澄清

如何使用.Aggregate从多个集合中获取数据,包括使用Mongoose+NextJS的SUM值

如何删除 bootstrap 手风琴上的边框

如何更改TimePicker中下拉菜单的背景 colored颜色 和字体 colored颜色 - MUI React

将水平滚动视图添加到底部导航选项卡

为什么我会收到此错误:无法在我的react 包上读取 null 的属性(读取useState)?

有没有办法在用户离开页面时防止输入模糊?

MUI TextField Select 菜单的最大高度

React - 错误边界未捕获错误

React js中不记名令牌中的空间问题

如何在 React 中使用 debounce hooks

表单错误后 Ionic React 无法 Select 单选按钮

NextJS htaccess 设置

Cypress ,重试不再附加到 DOM 的元素

React Router 6.4CreateBrowserRouter子元素不显示

如何在 React JS 上使文本中的单词可点击

你如何使用 refs 访问 React 中映射子项的值?

警告:您在没有 `onChange` 处理程序的情况下为表单字段提供了 `value` 属性