reactjs2d-context-api

I'm trying to use context api but the value of my Consumer return undefined in the console


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.


Solution

  • 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:

    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!