1

I am trying to use the new ReactJs Context, as an alternative to Redux, however I am getting an error of.

Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

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

Here is the code for my layout which I have wrapped in the MyProvider tag

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

Here is the context code which I am importing

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

Here is the place the provider is being consumed

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

any help would be greatly appreciated.

5
  • 1
    Is NavMenu exported correctly? Can you please show the code of it? Commented Aug 3, 2018 at 12:24
  • You are not using anywhere the MyProvider.Consumer. MyProvider is the output of React.createContext() so not a valid React element by itself Commented Aug 3, 2018 at 12:25
  • Sorry I have used MyProvider.Consumer somewhere I just didn't add it to make the question shorter, I will amend Commented Aug 3, 2018 at 12:30
  • @LucaFabbri MyProvider is the react component. The naming is really confusing here. MyContext is the output of React.createContext(). @user3284707 You should fix this. Commented Aug 3, 2018 at 12:33
  • I unfortunately can not test this at the moment, but will update when I have Commented Aug 3, 2018 at 13:17

2 Answers 2

1

Let me provide another answer. This is similar to @Tholle's but I think it is closer to your intention. If not, consider this as a simple alternative.

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"));
Sign up to request clarification or add additional context in comments.

11 Comments

Thank you for your reply, I have unfortunately not been able to test this yet. I will try this out later and then let you know.
I'm afraid this still isn;t working, i'm still getting the same error message "Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object."
Ok - so this isn't the exact error but something pretty similar, worked great when everything was in one js file, as soon as I moved the context out it then broke..? codesandbox.io/s/9y1krp798w - EDIT - Actually I forgot to export so no wonder it didnt work...
Yes this does in this example... which annoyingly means it's something else... I'm using the visual studio template which has a load of other routing additions to it which may be causing issues
You said this does now work on your dev env right and same problem in the title? Then as @Hardik Modha asked is your NavMenu exported properly?
|
1

You should use {this.state} as value for the Provider, not "{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>
    );
  }
}

You also have to use the MyContext.Consumer component to use the value from the provider, and this component takes a function as child.

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

7 Comments

Thank you for this answer, I am unable to test this at the moment but will let you know how I get on when I can later.
I'm afraid this still isn;t working, i'm still getting the same error message "Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object."
@user3284707 That's frustrating. Try creating a Minimal, Complete, and Verifiable example in e.g. CodeSandbox. There might be something else that is wrong.
Done a sample in codesandbox, not the exact error but very similar codesandbox.io/s/x93nnww22q- EDIT - Actually I forgot to export so no wonder it didnt work...
@user3284707 Ah, so the real issue was an export issue? Glad you found it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.