简体   繁体   English

React useContext throws无效的钩子调用错误

[英]React useContext throws Invalid hook call error

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. 我试图使用useContext将值从上下文提供程序传递给使用者,并访问render函数之外的值。

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. 钩子只能在函数组件的主体内部调用。


If you want to use hooks they are designed for functional 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: 如果要在基于类的组件中使用它,那么只需在类中将其设置为静态contextType,然后就可以在组件中使用this.context ,如下所示:

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 这是一个沙箱,向您展示它正在使用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 你得到上面的错误,因为Hooks意味着在函数组件内使用而不是类组件,而你试图在main组件的componentDidMount中使用它,它是一个类组件

You can rewrite your code for Main component using useContext hook like 您可以使用useContext hook重写主组件的代码

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 或者以类似的方式以不同的方式使用Context

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. 这是Main.js文件的内容。 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. 这是App.js文件的内容。 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. React Hooks直接针对功能组件实现,以便为它们提供成为有状态的可能性。 Class-based components were stateful all the time, so you have to use their own state API. 基于类的组件始终是有状态的,因此您必须使用自己的state API。

Working demo is available here . 这里有工作演示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM