【问题标题】:ReactJs context - Element type is invalidReactJs 上下文 - 元素类型无效
【发布时间】:2018-08-03 12:19:38
【问题描述】:

我正在尝试使用新的 ReactJs Context 作为 Redux 的替代品,但是我收到了一个错误。

Invariant Violation:元素类型无效:预期为字符串(对于内置组件)或类/函数(对于复合组件),但得到:对象。

https://reactjs.org/docs/context.html

这是我在 MyProvider 标记中包装的布局代码

import React, { Component } from "react";
import { NavMenu } from "./NavMenu";
import { MyProvider } from "../contexts/context";

export class Layout extends Component {
    render() {
        return (
            <MyProvider>
                <div className="container-fluid">
                    <div className="row">
                        <div className="col-sm-3">
                            <NavMenu />
                        </div>
                        <div className="col-sm-9">
                            {this.props.children}
                        </div>
                    </div>
                </div>
            </MyProvider>
        );
    }
}

这是我要导入的上下文代码

import React, { Component } from "react";
export const MyContext = React.createContext();

export class MyProvider extends Component {
    state = {
        name: 'test name'
    }
    render() {
        return (
            <MyContext.Provider value="{this.state}">
                {this.props.children}
            </MyContext.Provider>
        )
    }
}

这里是提供者被消费的地方

import React, { Component } from "react";
import { RouteComponentProps } from "react-router";
import { MyProvider } from "../contexts/context";

export class Counter extends Component {
    render() {
        return <div className="m-2">
            <MyContext.Consumer>
                {(c) => (<p>My name is {c.state.name}</p>)}
            </MyContext.Consumer>
        </div>;
    }
}

任何帮助将不胜感激。

【问题讨论】:

  • NavMenu 是否导出正确?能否请您显示它的代码?
  • 您没有在任何地方使用MyProvider.ConsumerMyProviderReact.createContext() 的输出,所以它本身不是一个有效的 React 元素
  • 对不起,我在某处使用了 MyProvider.Consumer,只是没有添加它以缩短问题,我会修改
  • @LucaFabbri MyProvider 是反应组件。这里的命名真的很混乱。 MyContextReact.createContext() 的输出。 @user3284707 你应该解决这个问题。
  • 很遗憾,我目前无法测试这个,但我会更新

标签: javascript reactjs react-context


【解决方案1】:

让我提供另一个答案。这类似于@Tholle,但我认为它更接近您的意图。如果没有,请将此视为一个简单的替代方案。

const MyContext = React.createContext()

class MyProvider extends React.Component {
  state = {
    name: 'test name'
  }
  render() {
    return (
      <MyContext.Provider value={this.state}>
        {this.props.children}
      </MyContext.Provider>
    )
  }
}

class Layout extends React.Component {
  render() {
    return (
      <MyProvider>
        <div className="container-fluid">
          <div className="row">
            <div className="col-sm-3">
            <NavMenu />
            </div>
            <div className="col-sm-9">
              {this.props.children}
            </div>
          </div>
        </div>
      </MyProvider>
    );
  }
}

class Counter extends React.Component {
  render() {
    return <div className="m-2">
      <MyContext.Consumer>
        {c => <p>My name is {c.name}</p>}
      </MyContext.Consumer>
    </div>;
  }
}

ReactDOM.render(<Layout><Counter /></Layout>, document.getElementById("root"));

【讨论】:

  • 感谢您的回复,很遗憾我还无法对此进行测试。我稍后会试试这个,然后告诉你。
  • 恐怕这仍然无法正常工作,我仍然收到相同的错误消息“不变违规:元素类型无效:需要字符串(用于内置组件)或类/function(用于复合组件)但得到:对象。”
  • 好的 - 所以这不是确切的错误,而是非常相似的东西,当所有内容都在一个 js 文件中时效果很好,只要我将上下文移出然后它就坏了..? codesandbox.io/s/9y1krp798w - 编辑 - 实际上我忘了导出所以难怪它不起作用......
  • 是的,在这个例子中确实如此......这令人讨厌地意味着它是别的东西......我正在使用 Visual Studio 模板,它有很多其他路由添加到它可能会导致问题
  • 您说这现在可以在您的开发环境中正常工作,并且标题中存在同样的问题?然后正如@Hardik Modha 问的那样,您的NavMenu 是否正确导出?
【解决方案2】:

您应该使用 {this.state} 作为 Provider 的值,而不是 "{this.state}"

export const MyContext = React.createContext();

export class MyProvider extends Component {
  state = {
    name: "test name"
  };

  render() {
    return (
      <MyContext.Provider value={this.state}>
        {this.props.children}
      </MyContext.Provider>
    );
  }
}

您还必须使用MyContext.Consumer 组件才能使用来自提供程序的value,并且该组件将一个函数作为子函数。

import { MyProvider, MyContext } from "../contexts/context";

export class Layout extends Component {
  render() {
    return (
      <MyProvider>
        <MyContext.Consumer>
          {value => (
            <div className="container-fluid">
              <div className="row">
                <div className="col-sm-3">
                  <NavMenu />
                </div>
                <div className="col-sm-9">{this.props.children}</div>
              </div>
            </div>
          )}
        </MyContext.Consumer>
      </MyProvider>
    );
  }
}

【讨论】:

  • 感谢您的回答,我目前无法对此进行测试,但稍后会告诉您我的进展情况。
  • 恐怕这仍然无法正常工作,我仍然收到相同的错误消息“不变违规:元素类型无效:需要字符串(用于内置组件)或类/function(用于复合组件)但得到:对象。”
  • @user3284707 这令人沮丧。尝试在例如创建Minimal, Complete, and Verifiable example CodeSandbox。可能还有其他问题。
  • 在codesandbox中做了一个样本,不是确切的错误,但非常相似codesandbox.io/s/x93nnww22q- 编辑 - 实际上我忘记导出所以难怪它不起作用......
  • @user3284707 啊,所以真正的问题是出口问题?很高兴你找到它。
猜你喜欢
  • 2020-01-27
  • 1970-01-01
  • 2020-05-12
  • 2017-05-16
  • 2019-09-01
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
相关资源
最近更新 更多