reactjsreact-hooksreact-propsreact-contextcreatecontext

The h2 component within the App.js doesn't render dynamically. What can be the issue?


These are my components that are within the same directory:

// App.js
import "./styles.css";
import React, { useState } from "react";
import Nav from "./Nav";
import { AppProvider } from "./context";

export default function App() {
  const [signedIn, setSignedIn] = useState(true);

  return (
    <div className="App my-3">
      <AppProvider>
        <Nav />
        <h2 className="my-2">{signedIn ? "Signed In!" : "Signed Out!"}</h2>
      </AppProvider>
    </div>
  );
}


// Nav.js
import Btn from "./Btn";

const Nav = () => {
  return <Btn />;
};

export default Nav;


// Btn.js
import "bootstrap/dist/css/bootstrap.min.css";
import { useContext } from "react";
import { context } from "./context";

const Btn = () => {
  const [signedIn, setSignedIn] = useContext(context);
  const handleButtonClick = () => {
    setSignedIn((prevState) => !prevState);
  };

  return (
    <button className="btn btn-primary" onClick={handleButtonClick}>
      {signedIn ? "Signed In!" : "Signed Out!"}
    </button>
  );
};

export default Btn;


// context.js
import React, { useState } from "react";

const context = React.createContext();

const AppProvider = ({ children }) => {
  const [signedIn, setSignedIn] = useState(true);

  return (
    <context.Provider value={[signedIn, setSignedIn]}>
      {children}
    </context.Provider>
  );
};

export { context, AppProvider };

This problem arose only when I tried creating a separate context.js file. It works perfectly fine when the code is as follows:

// App.js
import "./styles.css";
import React, { useState } from "react";
import Nav from "./Nav";

export const context = React.createContext();

export default function App() {
  const [signedIn, setSignedIn] = useState(true);

  return (
    <div className="App my-3">
      <context.Provider value={[signedIn, setSignedIn]}>
        <Nav />
        <h2 className="my-2">{signedIn ? "Signed In!" : "Signed Out!"}</h2>
      </context.Provider>
    </div>
  );
}


// Btn.js
import "bootstrap/dist/css/bootstrap.min.css";
import { useContext } from "react";
import { context } from "./App";

const Btn = () => {
  const [signedIn, setSignedIn] = useContext(context);
  const handleButtonClick = () => {
    setSignedIn((prevState) => !prevState);
  };

  return (
    <button className="btn btn-primary" onClick={handleButtonClick}>
      {signedIn ? "Signed In!" : "Signed Out!"}
    </button>
  );
};

export default Btn;

Can you please help me out here? I'm still a beginner to react so I am unsure as to what I should be doing to overcome this error. I tried several methods but none of them seemed to work


Solution

  • Components that want to use values from the context have to explicitly say that they want it. You need to wrap your h2 in another function component and declare that it wants to use the context as below:

    import React, { useContext } from "react";
    import Btn from "./Btn.js";
    import { AppProvider, context } from "./Context";
    
    const H2 = () => {
      const [signedIn] = useContext(context);
      return <h2 className="my-2">{signedIn ? "Signed In!" : "Signed Out!"}</h2>;
    };
    
    export default function App() {
      return (
        <div className="App my-3">
          <AppProvider>
            <Btn />
            <H2 />
          </AppProvider>
        </div>
      );
    }
    

    Demo:

    Edit clever-lumiere-mnsrrd