Home > Software design >  TypeError: [setState with createContext] is not a function - React
TypeError: [setState with createContext] is not a function - React

Time:10-09

I am using React's Context API to call setCurrentUser below. But it gives me this error:

TypeError: setCurrentUser is not a function.

Upon logging console.log(useContext(globalContext)), I get the empty object {}.

I have manually converted my project from TS(where it worked by specifying setCurrentUser as type Dispatch) to JS, so I am not sure if that broke something...at least my react and react-dom packages should be current.

How do we make this work with JS? Thanks

Router.jsx - where I am calling setCurrentUser

import React, { useContext, useEffect } from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import LoginPg from "../pages/LoginPg/LoginPg";
import ErrorHandler from "./ErrorHandler";
import ErrorPg from "../pages/ErrorPg/ErrorPg";
import useGet from "../../server_api/useGet";
import ProtectedRoute from "./ProtectedRoute";
import HomePg from "../pages/HomePg/HomePg";
import { globalContext } from "../../store/context/globalContext";
import CalendarPg from "../pages/Calendar/CalendarPg";

function Router() {
  const { currentUser, setCurrentUser } = useContext(globalContext);
  const [doGet] = useGet();
  let user;
  console.log(useContext(globalContext)); // <==== logs: {}

  useEffect(() => {
    doGet("auth/authenticate", (res) => {
      if (res) {
        user = res.username;
        setCurrentUser(res);
      } else {
        console.log("Router: user not authenticated");
      }
    });
  }, []);

  return (
    <BrowserRouter>
      <ErrorHandler>
      <Switch>
        <Route path="/error" component={ErrorPg} />
        <Route path="/login" component={LoginPg} />

        <ProtectedRoute
          path="/calendar"
          Component={CalendarPg}
          isAuth={currentUser}
          key="uniquevalue"
        />
        <ProtectedRoute path="/" Component={HomePg} isAuth={currentUser} />
      </Switch>
      </ErrorHandler>
    </BrowserRouter>
  );
}

export default Router;

globalContext.jsx

import { createContext, useState } from "react";

export const globalContext = createContext({});

export default function GlobalContext(props) {
  const [currentUser, setCurrentUser] = useState(null);

  return (
    <globalContext.Provider value={{ currentUser, setCurrentUser }}>
      {props.children}
    </globalContext.Provider>
  );
}

package.json

{
  "name": "test",
  "version": "0.1.0",
  "private": true,
  "homepage": "/",
  "dependencies": {
    "@fullcalendar/daygrid": "^5.9.0",
    "@fullcalendar/interaction": "^5.9.0",
    "@fullcalendar/react": "^5.9.0",
    "@fullcalendar/timegrid": "^5.9.0",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "antd": "^4.16.13",
    "axios": "^0.21.1",
    "bootstrap": "^5.1.1",
    "font-awesome": "^4.7.0",
    "fullcalendar": "^5.9.0",
    "lodash": "^4.17.21",
    "moment": "^2.29.1",
    "query-string": "^4.3.4",
    "react": "^17.0.2",
    "react-calendar": "^3.4.0",
    "react-dom": "^17.0.2",
    "react-helmet": "^6.1.0",
    "react-modal": "^3.14.3",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.3",
    "sass": "^1.39.2",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "cypress": "npx cypress open"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "cypress": "^7.5.0"
  }
}

CodePudding user response:

You need the consumer (Router) to be a child of the provider (GlobalContext).

Also your component names should start with an Upper case.

import { GlobalContext } from "../../store/context/GlobalContext";

const App = () => {
  const [currentUser, setCurrentUser] = useState(DEFAULT_USER);

  return (
    <GlobalContext.Provider value={{ currentUser, setCurrentUser }}>
      <Router />
    </GlobalContext.Provider>
  );
};
  • Related