admin管理员组

文章数量:1201569

I am trying to pass a value from a context provider to a consumer using useContext and access the value outside of the render function.

My provider looks like so:

export const AppContext = React.createContext();

export class App extends React.Component(){
    render(){
        <AppContext.Provider value={{ name: 'John' }} ><Main /></AppContext>   
    }
}

My consumer looks like so

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

export class Main extends React.Component(){
    componentDidMount(){
        const value = useContext(AppContext);
    }
    render(){
        return (
            <div>Main Component</div>
        )
    }
}

The error is this:

Invalid hook call. Hooks can only be called inside of the body of a function component.


I am trying to pass a value from a context provider to a consumer using useContext and access the value outside of the render function.

My provider looks like so:

export const AppContext = React.createContext();

export class App extends React.Component(){
    render(){
        <AppContext.Provider value={{ name: 'John' }} ><Main /></AppContext>   
    }
}

My consumer looks like so

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

export class Main extends React.Component(){
    componentDidMount(){
        const value = useContext(AppContext);
    }
    render(){
        return (
            <div>Main Component</div>
        )
    }
}

The error is this:

Invalid hook call. Hooks can only be called inside of the body of a function component.


Share Improve this question asked Apr 29, 2019 at 3:37 SinghSingh 1,9883 gold badges22 silver badges31 bronze badges 1
  • 2 The error clearly says that hooks can only be called inside function component, and you are trying to use inside class based component. Create function component and it should work. – tarzen chugh Commented Apr 29, 2019 at 5:29
Add a comment  | 

4 Answers 4

Reset to default 15

If you want to use hooks they are designed for function components. Like so:

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

const Main = () => {
  const value = useContext(AppContext);

  return(
    <div>Main Component</div>
  );
}

If you want to use it in a class based component then just set it as a static contextType in your class and then you can use it with this.context in your component like so:

import React from 'react';
import { AppContext } from './App';

class Main extends React.Component(){

  static contextType = AppContext;

  componentDidMount(){
    const value = this.context;
  }
  render(){
    return (
      <div>Main Component</div>
    )
  }
}

Edit: Remove your context from your app component and place it in its own component. I think you are receiving conflicts in your exporting of your context.

so your app component should look like:

import React from "react";
import Context from "./Context";
import Main from "./Main";

class App extends React.Component {
  render() {
    return (
      <Context>
        <Main />
      </Context>
    );
  }
}

export default App;

Your main component should be like:

import React from "react";
import { AppContext } from "./Context";

class Main extends React.Component {
  static contextType = AppContext;

  render() {
    return <div>{this.context.name}</div>;
  }
}

export default Main;

and your context component should be like:

import React from "react";

export const AppContext = React.createContext();

class Context extends React.Component {
  state = {
    name: "John"
  };

  //Now you can place all of your logic here
  //instead of cluttering your app component
  //using this components state as your context value
  //allows you to easily write funcitons to change
  //your context just using the native setState 
  //you can also place functions in your context value
  //to call from anywhere in your app
  render() {
    return (
      <AppContext.Provider value={this.state}>
        {this.props.children}
      </AppContext.Provider>
    );
  }
}

export default Context;

Here is a sandbox to show you it working CodSandbox

You get the above error because Hooks are meant to be used inside functional components and not class component whereas you try to use it within componentDidMount of Main component which is a class component

You can rewrite your code for Main component using useContext hook like

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

export const Main =() =>{
    const value = useContext(AppContext);
    return (
        <div>Main Component</div>
    )
}

or use Context in a different way with class like

import React from 'react';
import { AppContext } from './App';

class Main extends React.Component {
    componentDidMount(){
        const value = this.context;
        // use value here. Also if you want to use context elsewhere in class
        // you can use if from this.context
    }
    render(){
        return (
            <div>Main Component</div>
        )
    }
}

Main.contextType = AppContext;

export { Main };

Hooks only work with stateless components. You are trying to use it in class component.

Here is the content for Main.js file. Uncomment the commented part if you want to use class-based component instead of the functional one.

import React from "react";
import { AppContext } from "./App";

/** UNCOMMENT TO USE REACT CLASS COMPONENT */
// class Main extends React.Component() {
//   render() {
//     return (
//       <AppContext.Consumer>
//         {value => <div>It's Main component. Context value is ${value.name}</div>}
//       </AppContext.Consumer>
//     );
//   }
// }

const Main = () => {
  const value = React.useContext(AppContext);

  return <div>It's Main component. Context value is ${value.name}</div>;
};

export default Main;

Here is the content for App.js file. Uncomment the commented part if you want to use class-based component instead of the functional one.

import React from "react";
import ReactDOM from "react-dom";

import Main from "./Main";

export const AppContext = React.createContext();

/** UNCOMMENT TO USE REACT CLASS COMPONENT */
// export class App extends React.Component() {
//   render() {
//     return (
//       <AppContext.Provider value={{ name: "John" }}>
//         <Main />
//       </AppContext.Provider>
//     );
//   }
// }

const App = () => (
  <AppContext.Provider value={{ name: "John" }}>
    <Main />
  </AppContext.Provider>
);

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

React Hooks were implemented directly for the functional components in order to give them the possibility to become stateful. Class-based components were stateful all the time, so you have to use their own state API.

Working demo is available here.

本文标签: javascriptReact useContext throws Invalid hook call errorStack Overflow