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

标签 javascript reactjs

我一直在 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/

相关文章:

reactjs - 如何在 react 表访问器中调用函数? ( react )

javascript - child 里面 Angular child

javascript - 在 React/React native 中使用进度百分比循环或递归获取大量数据

javascript - postman :您需要启用 JavaScript 才能运行此应用

javascript - 如何使用 Immutable.js 提供 Flux 存储之间的依赖关系?

javascript - React.js : How to render separated jsx modules from one app. jsx 文件?

javascript - D3.JS : Multiple root points 中的可折叠图

php - 缓存 php 生成的 javascript 页面

javascript - 验证依赖于其他输入的输入

使用 math.random 的 Javascript 单选按钮鼠标悬停移动图像