草庐IT

javascript - React 16.3 Context API——提供者/消费者问题

coder 2025-03-21 原文

我一直在 React 16.3.1 ContextAPI 上做一些实验。我遇到了一些我无法理解的事情。我希望我能得到你的帮助。

注意:问题已经解决,但不是我要找的解决方案。

让我们首先对同一文件 Index.js 中的多个组件进行实验。

import React, { Component, createContext } from 'react';
const { Provider, Consumer } = createContext();

class AppProvider extends Component {
  state = {
    name: 'Superman',
    age: 100
  };

  render() {
    const increaseAge = () => {
      this.setState({ age: this.state.age + 1 });
    };

    const decreaseAge = () => {
      this.setState({ age: this.state.age - 1 });
    };
    return (
      <Provider
        value={{
          state: this.state,
          increaseAge,
          decreaseAge
        }}
      >
        {this.props.children}
      </Provider>
    );
  }
}

class Person extends Component {
  render() {
    return (
      <div className="person">
        <Consumer>
          {context => (
            <div>
              <p>I'm {context.state.name}</p>
              <p>I'm {context.state.age}</p>
              <button onClick={context.increaseAge}>
                <span>+</span>
              </button>
              <button onClick={context.decreaseAge}>
                <span>-</span>
              </button>
            </div>
          )}
        </Consumer>
      </div>
    );
  }
}

class App extends Component {
  render() {
      return (
        <AppProvider>
          <div className="App">
            <p>Imma Apps</p>
            <Person />
          </div>
        </AppProvider>
      );
    }
  }

export default App;

因此,这渲染完美,没有任何错误。我能够看到名字(超人)和年龄(100)。我可以将年龄增加和减少 1。

如你所见,我导入了{createContext}从 react 然后创建 {Provider, Consumer} .包裹<Provider>状态值和 <Consumer> .

下一个实验,是从 index.js 中精确复制每个组件并将它们分别粘贴到它们自己的文件中。

AppProvider.js

import React, { Component, createContext } from 'react';
const { Provider, Consumer } = createContext();

class AppProvider extends Component {
  state = {
    name: 'Superman',
    age: 100
  };

  render() {
    const increaseAge = () => {
      this.setState({ age: this.state.age + 1 });
    };

    const decreaseAge = () => {
      this.setState({ age: this.state.age - 1 });
    };
    return (
      <Provider
        value={{
          state: this.state,
          increaseAge,
          decreaseAge
        }}
      >
        {this.props.children}
      </Provider>
    );
  }
}
export default AppProvider;

Person.js

import React, { Component, createContext } from 'react';
const { Provider, Consumer } = createContext();

class Person extends Component {
  render() {
    return (
      <div className="person">
        <Consumer>
          {context => (
            <div>
              <p>I'm {context.state.name}</p>
              <p>I'm {context.state.age}</p>
              <button onClick={context.increaseAge}>
                <span>+</span>
              </button>
              <button onClick={context.decreaseAge}>
                <span>-</span>
              </button>
            </div>
          )}
        </Consumer>
      </div>
    );
  }
}
export default Person;

App.js

import React, { Component, createContext } from 'react';
const { Provider, Consumer } = createContext();

class App extends Component {
  render() {
      return (
        <AppProvider>
          <div className="App">
            <p>Imma Apps</p>
            <Person />
          </div>
        </AppProvider>
      );
    }
  }

export default App;

结果,我收到错误 - TypeError: Cannot read property 'state' of undefined

我无法理解确切的错误是什么。我所做的只是将每个错误复制并粘贴到文件中,而不更改任何语法。

虽然,替代方法是创建一个新文件并添加以下语法...

上下文.js

import { createContext } from 'react';
const Context = createContext();
export default Context;

然后进入每个文件(AppProvider.jsPerson.jsApp.js)并替换...

import React, { Component, createContext } from 'react';
const { Provider, Consumer } = createContext(); '

...进入...

import Context from './Context.js'; .也替换... <Provider>进入<Context.Provider><Consumer>进入<Context.Consumer> .

这消除了错误。但是,这不是我正在寻找的解决方案。我想用 <Provider>标记而不是 <Context.Provider> .

问题是,为什么会出现此错误?

为什么我不能使用这个方法...

import React, { Component, createContext } from 'react';
const { Provider, Consumer } = createContext(); '

对于单独文件中的每个组件,所以我可以使用 <Provider>标签 ?

是否有任何方法可以获得我正在寻找的解决方案?

感谢您的帮助,在此先致谢。

最佳答案

您遇到了TypeError: Cannot read property 'state' of undefined。 因为每次调用 const { Provider, Consumer } = createContext(); 它都会创建一个新对象,需要导出该对象以便消费者使用该特定对象。

所以在 person.js 中 当您尝试执行 {context.state.age} 时,它确实没有此对象的状态,您只是创建了一个新的 Context,它是空的,或者更确切地说是具有 React 内部方法和属性。

因此,为了使用同一个对象,只需导出它,就像您在 Context.js 中所做的那样,而不是:

import { createContext } from 'react';
const Context = createContext();
export default Context;

替换为:

import { createContext } from 'react';
const { Provider, Consumer } = createContext();
export { Consumer, Provider };

然后当你想在其他文件中使用它时(意思是导入它)只需调用:

import { Consumer, Provider } from './Context.js';

关于javascript - React 16.3 Context API——提供者/消费者问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49708792/

有关javascript - React 16.3 Context API——提供者/消费者问题的更多相关文章

  1. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  2. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  3. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  4. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  5. 深度学习12. CNN经典网络 VGG16 - 2

    深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG

  6. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

  7. ruby-on-rails - 我将 Rails3 与 tinymce 一起使用。如何呈现用户关闭浏览器javascript然后输入xss? - 2

    我有一个用Rails3编写的站点。我的帖子模型有一个名为“内容”的文本列。在帖子面板中,html表单使用tinymce将“content”列设置为textarea字段。在首页,因为使用了tinymce,post.html.erb的代码需要用这样的原始方法来实现。.好的,现在如果我关闭浏览器javascript,这个文本区域可以在没有tinymce的情况下输入,也许用户会输入任何xss,比如alert('xss');.我的前台会显示那个警告框。我尝试sanitize(@post.content)在posts_controller中,但sanitize方法将相互过滤tinymce样式。例如

  8. ruby - 使用 Selenium WebDriver 启用/禁用 javascript - 2

    出于某种原因,我必须为Firefox禁用javascript(手动,我们按照提到的步骤执行http://support.mozilla.org/en-US/kb/javascript-settings-for-interactive-web-pages#w_enabling-and-disabling-javascript)。使用Ruby的SeleniumWebDriver如何实现这一点? 最佳答案 是的,这是可能的。而是另一种方式。您首先需要查看链接Selenium::WebDriver::Firefox::Profile#[]=

  9. ruby - Watir-Webdriver 是否支持点击目标为 javascript 的链接? - 2

    我是Ruby和Watir-Webdriver的新手。我有一套用VBScript编写的站点自动化程序,我想将其转换为Ruby/Watir,因为我现在必须支持Firefox。我发现我真的很喜欢Ruby,而且我正在研究Watir,但我已经花了一周时间试图让Webdriver显示我的登录屏幕。该站点以带有“我同意”区域的“警告屏幕”开头。用户点击我同意并显示登录屏幕。我需要单击该区域以显示登录屏幕(这是同一页面,实际上是一个表单,只是隐藏了)。我整天都在用VBScript这样做:objExplorer.Document.GetElementsByTagName("area")(0).click

  10. ruby - 单个 EventMachine react 器中的多个服务器 - 2

    是否可以在单个事件机器中运行多个服务器?我的意思是,多个服务可以由一个客户端连接同时使用。例如,登录服务器对用户进行身份验证,然后用户可以同时使用聊天室和简单的游戏,例如带有单个客户端套接字的跳棋?或者我是否需要为每个服务使用多个事件机器react器? 最佳答案 我试过了,它正在工作:#!/usr/bin/envrubyrequire'eventmachine'moduleEchoServerdefpost_initputs"--someoneconnectedtotheechoserver!"enddefreceive_datad

随机推荐