React.js Context API: useContext is returning null inside custom hook

141 views Asked by At

I'm trying to create & use a custom hook for a React Context. Inside this hook, I'm trying to pass the defined context, SectionContext, into useContext , like so:

export const useSectionContext= () => {
  const context = useContext<TSectionContext | null>(SectionContext); // Why is this null?

  if (!context) {
    throw new Error("Must use useSectionContext within the context of SectionProvider.");
  }
  return context;
};

I initialized SectionContext & a Provider, like so:

export const SectionContext = createContext<TSectionContext | null>(null);

export const SectionProvider = ({ children }: { children: ReactNode }) => {
  const [allDogs, setAllDogs] = useState<Dog[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [activeTab, setActiveTab] = useState<Tab>("all-dogs");

  useEffect(() => {
    Requests.getAllDogs()
      .then(setAllDogs)
      .finally(() => setIsLoading(false));
  }, []);

  // Helper functions that aren't relevant to this question
  
  // sectionContextValues below is an object containing helper functions & state values
  
  return (
    <SectionContext.Provider value={sectionContextValues}>
      {children}
    </SectionContext.Provider>
  );
};

In the App.tsx file, I am then trying to wrap the <Section> component inside this provider, like so:

<SectionProvider>
    <Section label={"Dogs: "}>
      {activeTab === "no-dogs" ? <CreateDogForm /> : <Dogs />}
    </Section>
  </SectionProvider>

The error I am encountering is stemming from the fact that the useContext in the first code block above is returning null, and I haven't yet figured out why.

There are no problems with the imports or exports, btw. I also tried setting the initial value of SectionContext to undefined, but got the same result.

If someone could provide me with some insight as to why this could be happening, I would love to hear it. Please, let me know if you need me to clarify anything.

1

There are 1 answers

0
brucetwarze On

I learned that I cannot call useSectionContext in the same component I am importing SectionProvider. In my case, I had to wrap the necessary components inside SectionProvider in the parent of App.tsx, which is main.tsx. In the end, this is what my code looked like:

// in main.tsx:
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import "./App.css";
import "./index.css";
import { Toaster } from "react-hot-toast";
import { App } from "./App";
import { SectionProvider } from "./sectionProvider";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <Toaster />
    <SectionProvider>
      <App />
    </SectionProvider>
  </React.StrictMode>
);
// in App.tsx:
import { Section } from "./Components/Section";
import { Dogs } from "./Components/Dogs";
import { CreateDogForm } from "./Components/CreateDogForm";
import { useSectionContext } from "./useSectionContext";

export function App() {
  const { activeTab } = useSectionContext();
  return (
    <div className="App" style={{ backgroundColor: "skyblue" }}>
      <header>
        <h1>pup-e-picker (Functional)</h1>
      </header>
      <Section label={"Dogs: "}>
        {activeTab === "no-dogs" ? <CreateDogForm /> : <Dogs />}
      </Section>
    </div>
  );
}