Реагирует useContext выбрасывает Недопустимая ошибка вызова ловушки - PullRequest
1 голос
/ 29 апреля 2019

Я пытаюсь передать значение от поставщика контекста потребителю с помощью useContext и получить доступ к значению вне функции рендеринга.

Мой провайдер выглядит так:

export const AppContext = React.createContext();

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

Мой потребитель выглядит так

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>
        )
    }
}

Ошибка в следующем:

Недопустимый вызов ловушки.Хуки могут быть вызваны только внутри тела компонента функции.


Ответы [ 4 ]

4 голосов
/ 29 апреля 2019

Если вы хотите использовать крючки, они предназначены для функциональных компонентов.Например:

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

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

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

Если вы хотите использовать его в компоненте на основе классов, просто установите его как статический 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>
    )
  }
}

Редактировать: удалить свой контекст из компонента приложения и поместить его в свой собственный компонент.Я думаю, что вы получаете конфликты при экспорте контекста.

, поэтому ваш компонент приложения должен выглядеть так:

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;

Ваш основной компонент должен выглядеть так:

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;

и ваш контекстный компонент должен выглядеть следующим образом:

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;

Вот песочница, чтобы показать вам, как она работает CodSandbox

2 голосов
/ 29 апреля 2019

Вы получаете вышеупомянутую ошибку, потому что хуки предназначены для использования внутри функциональных компонентов, а не компонента класса, тогда как вы пытаетесь использовать его в componentDidMount компонента Main, который является компонентом класса

Вы можете переписать свой код для компонента Main, используя хук useContext, например

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

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

или используйте 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 };
0 голосов
/ 29 апреля 2019

Вот содержимое файла Main.js. Раскомментируйте прокомментированную часть, если вы хотите использовать компонент на основе классов вместо функционального.

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;

Вот содержимое файла App.js. Раскомментируйте прокомментированную часть, если вы хотите использовать компонент на основе классов вместо функционального.

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 были реализованы непосредственно для функциональных компонентов, чтобы дать им возможность стать с состоянием. Компоненты на основе классов постоянно находились в состоянии, поэтому вы должны использовать их собственный state API.

Рабочая демоверсия доступна здесь .

0 голосов
/ 29 апреля 2019

Крючки работают только с компонентами без сохранения состояния.Вы пытаетесь использовать его в компоненте класса.

...