Search code examples
reactjsreact-hooksreact-contextcodesandbox

React Context in CodeSandbox


I'm having issues with React Context using CodeSandbox.

My basic example:

App.js

import React, { useEffect, useContext } from "react";
import { FirmsContext } from "./FirmsContext";

export default function App() {
const { firms, fetchFirms } = useContext(FirmsContext);

  useEffect(() => {
   (async function getFirms() {
    await fetchFirms();
   })();
  }, [fetchFirms, firms]);

return (
 <div>
 </div>
);
}

FirmsConext.js

import React, { createContext, useReducer } from "react";
import FirmsReducer from "./FirmsReducer";

// INIT STATE
const initalState = {
 firms: []
};

// CREATE CONTEXT
export const FirmsContext = createContext(initalState);

// PROVIDER COMPONANT
export const FirmsProvider = ({ children }) => {
 const [state, dispatch] = useReducer(FirmsReducer, initalState);

 async function fetchFirms() {
  try {
   let response = await fetch("https://pokeapi.co/api/v2/pokemon-species/");
    dispatch({
     type: "GET_FIRMS",
     payload: response.result
    });
  } catch (err) {
    console.log(err);
   }
 }

return (
  <FirmsContext.Provider
    value={{
      firms: state.firms,
      fetchFirms
    }}
  >
    {children}
  </FirmsContext.Provider>
);
};

FirmsReducer.js

export default (state, action) => {
 switch (action.type) {
  case "GET_FIRMS":
    return {
      ...state,
      loading: false,
      firms: action.payload
    };
  default:
    return state;
 }
};

I am getting the following error: fetchFirms is not a function

This is showing up on the useEffect hook in app.js

   9 | 
  10 | useEffect(() => {
  11 |   (async function getFirms() {
> 12 |     await fetchFirms();
     |          ^
  13 |   })();
  14 | }, [fetchFirms, firms]);
  15 | 

I have very similar code elsewhere working fine, so not sure if this is CodeSandbox, or if I am just missing something?


Solution

  • If you want to use the values that the provider provides, you'll need to make <App /> a descendant of <FirmsProvider />, like so

    <FirmsProvider>
      <App />
    </FirmsProvider>
    

    otherwise you'll just see the initial value that the context was created with.