Home > database >  React Context defaultValue returns undefined when no provider is wrapped around the component tree
React Context defaultValue returns undefined when no provider is wrapped around the component tree

Time:03-28

I have been reading react docs to refresh my concepts. While reading, I came across this statement in context section:

The value argument passed to the function will be equal to the value prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the value argument will be equal to the defaultValue that was passed to createContext().

So naturally, I created some snippets to actually test the scenario.

My entry point (App.js):

import "./styles.css";
import WearLacoste from "./wearLacoste";
import WearPrada from "./wearPrada";
import OutFitProvider from "./outfitContext";

export default function App() {
  return (
    <div className="App">
      <h1>What to wear?</h1>
      <OutFitProvider>
        <WearPrada />
      </OutFitProvider>
      <WearLacoste />
    </div>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Notice that I have two components. These components return a string rendered on the browser, telling which dress to wear. One of the component name <WearPrada /> is wrapped by the provider, the other (<WearLacoste/>) is not, to test the defaultValue scenario.

Following is my context file (outfitContext.js):

import React, { useContext, useState } from "react";

const MyOutfitContext = React.createContext("Lacoste");

//a custom hook to consume context
export const useOutfit = () => {
  return useContext(MyOutfitContext);
};

const OutfitContextProvider = ({ children }) => {
  const [outfit, setOutfit] = useState("Prada");

  return (
    <MyOutfitContext.Provider value={{ outfit }}>
      {children}
    </MyOutfitContext.Provider>
  );
};

export default OutfitContextProvider;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

And finally both of my components, which do the exact same thing.

wearPrada.js :

import { useOutfit } from "./outfitContext";

const WearPrada = () => {
  const { outfit } = useOutfit();
  console.log("Outfit expects Prada", outfit);
  return <h1>Wearing {outfit} RN </h1>;
};

export default WearPrada;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

wearLacoste.js :

import { useOutfit } from "./outfitContext";

const WearLacoste = () => {
  const { outfit } = useOutfit();
  console.log("Outfit expects Lacoste", outfit);
  return <h1>Wearing {outfit} RN </h1>;
};

export default WearLacoste;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

My problem is:

The component wrapped in the provider is behaving as expected. It gets the state value initialised in context. But as claimed in the document, the component not wrapped in the provider still gets an undefined value instead of the defaultValue which is Lacoste (see outfitContext.js). Am I doing anything wrong here? Thanks in advance for the help.

CodePudding user response:

It seems that you have mixed the object { outfit: string } with a simple string. The context value is expected to be an object everywhere but when setting the default value you use a string.

I believe what you want is const MyOutfitContext = React.createContext({ outfit: "Lacoste" });

  • Related