最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React 16.3 Context API -- ProviderConsumer issues - Stack Overflow

programmeradmin10浏览0评论

I have been doing some experiment on React 16.3.1 ContextAPI. and I encountered into something that I couldn't fathom. I was hoping I could use your help.

Note: The problem have been solved but, its not the solution I am looking for.

Let start with first experiment on multiple ponents within same file 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;

As result, this render out perfect without any error. I am able to see name (Superman) and age (100). I am able to increase and decrease age by 1.

As you can see, I have imported {createContext} from react then created {Provider, Consumer}. Wrapped <Provider> with state value and <Consumer>.

Next Experiment, was exact copy each ponent from index.js and paste them separately into their own files.

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;

As result, I am getting error - TypeError: Cannot read property 'state' of undefined.

I am unable to grasp what the exactly error was.. All I did was copy and paste each into files without changing any syntax.

Although, Alternative method was to create a new file and add syntax following...

Context.js

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

Then go into each files (AppProvider.js. Person.js and App.js) and replace...

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

...into...

import Context from './Context.js';. Also replace... <Provider> into <Context.Provider> and <Consumer> into <Context.Consumer>.

And this killed the error. However, this is not the solution I am looking for. I wanted to use <Provider> tag instead of <Context.Provider>.

Question is, Why am I getting this error?

Why am I unable to use this method...

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

for each ponents in separate files so I could use <Provider> tag ?

Are there any way around to get the solution I'm looking for?

Your help is appreciated and Thanks in advance.

I have been doing some experiment on React 16.3.1 ContextAPI. and I encountered into something that I couldn't fathom. I was hoping I could use your help.

Note: The problem have been solved but, its not the solution I am looking for.

Let start with first experiment on multiple ponents within same file 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;

As result, this render out perfect without any error. I am able to see name (Superman) and age (100). I am able to increase and decrease age by 1.

As you can see, I have imported {createContext} from react then created {Provider, Consumer}. Wrapped <Provider> with state value and <Consumer>.

Next Experiment, was exact copy each ponent from index.js and paste them separately into their own files.

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;

As result, I am getting error - TypeError: Cannot read property 'state' of undefined.

I am unable to grasp what the exactly error was.. All I did was copy and paste each into files without changing any syntax.

Although, Alternative method was to create a new file and add syntax following...

Context.js

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

Then go into each files (AppProvider.js. Person.js and App.js) and replace...

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

...into...

import Context from './Context.js';. Also replace... <Provider> into <Context.Provider> and <Consumer> into <Context.Consumer>.

And this killed the error. However, this is not the solution I am looking for. I wanted to use <Provider> tag instead of <Context.Provider>.

Question is, Why am I getting this error?

Why am I unable to use this method...

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

for each ponents in separate files so I could use <Provider> tag ?

Are there any way around to get the solution I'm looking for?

Your help is appreciated and Thanks in advance.

Share Improve this question asked Apr 7, 2018 at 15:14 sirrussirrus 3431 gold badge7 silver badges17 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

Your are getting TypeError: Cannot read property 'state' of undefined. Beacuse every time you call const { Provider, Consumer } = createContext(); it creates a new object, this object need to be exported in order for consumers to consume this specific object.

So in person.js when you try doing {context.state.age} it really does not have state on this object, you just created a new Context which is empty or rather with React internal methods and properties.

So in order to consume the same object just export it, like you did in Context.js and instead of doing:

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

replace to:

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

Then when you want to use it in other files ( meaning import it ) just call:

import { Consumer, Provider } from './Context.js';
发布评论

评论列表(0)

  1. 暂无评论