-1

This is the code for my context api

import React, { Component } from "react";
const { Provider, Consumer } = React.createContext();
const MyContextProvider = Provider;
const MyContextConsumer = Consumer;
export { MyContextConsumer, MyContextProvider };

class UserState extends Component {
  state = {
    user: "JOHN"
  };

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

export default UserState;

And this is where I'm intended to use it but it returns undefined in the console. I'm looking for some help.

import React from "react";
import styled from "@emotion/styled";
import { Formik, Form, Field, ErrorMessage } from "formik";

import { MyContextConsumer } from "../../context/UserStateContext";

const StyledSignUp = styled.div`
  width: 50%;
  margin: 20px auto;
`;

const SignUpForm = ({ props, ...remainProps }) => {
  return (
    <StyledSignUp {...remainProps}>
      <MyContextConsumer>
        {context => {
          console.log(context, "CONTEXT API");
          return <div className='content'>content here</div>;
        }}
      </MyContextConsumer>
    </StyledSignUp>
  );
};

export default SignUpForm;

I wonder if I did anything wrong in the context code.

Mnguyen
  • 3
  • 4

1 Answers1

0

The problem you have here is that you were trying to destructure context too early. Personally I would split this out to 3 files. It also helps when you are using Git file history also!

  • User.context.js (this make importing easier to track
  • Provider - Usually this will be the highest node (which really needs it!)
  • Consumer - component which consumes the value

User.context.js:

import { createContext } from "react";

export const UserContext = createContext();

Provider - <UserState />:

import React, { Component } from "react";

import { UserContext } from '../../User.context.js' // some folder for context's

class UserState extends Component {
  state = {
    user: "JOHN"
  };

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

export default UserState;

Consumer - <SignUpForm />:

import React, { useContext } from "react";
import styled from "@emotion/styled";

import { UserContext } from '../../User.context.js' // some folder for context's

const StyledSignUp = styled.div`
  width: 50%;
  margin: 20px auto;
`;

// OLD WAY
const SignUpForm = ({ props, ...remainProps }) => {
  return (
    <UserContext.Consumer>
      {context => {
        console.log("CONTEXT API", context);

        return (
          <StyledSignUp {...remainProps}>
            <div className="content">content here</div>;
          </StyledSignUp>
        );
      }}
    </UserContext.Consumer>
  );
};

// React Hook way :)
const SignUpForm = ({ props, ...remainProps }) => {
  const context = useContext(UserContext);

  return (
    <StyledSignUp {...remainProps}>
      <div className="content">content here</div>;

      {/* Debug - Seeing is believing */}
      <pre>{JSON.stringify(context, null, 2)}</pre>
    </StyledSignUp>
  );
};

export default SignUpForm;

Let me know how you get on!

Neil
  • 971
  • 2
  • 12
  • 33
  • 1
    I love the react hook way that you did. I was able to debug it yesterday. The reason was that I forgot to pass it down from the highest component which is my layout.js where I included header and footer. But really, I just learned something new from you doing that react hook way. I will definitely play with it from now on. Thank you so much for helping me out with this. Do you have twitter or something that I can follow? @Neil – Mnguyen Jun 25 '19 at 01:02
  • Thanks for the kind words, I would look into twitter accounts such as dan_abramov and kentcdodds. If you could upvote the answer, if you found it helpful that would be great. – Neil Jun 25 '19 at 06:50