Skip to content
Advertisement

Changing the state of a context within an if-else in JavaScript

I tried making a global state by using a Context and have the following for my AuthProvider.js file

import { createContext, useState } from "react";

const AuthContext = createContext({});

export const AuthProvider = ({ children }) => {
    const [auth, setAuth] = useState({});

    return (
        <AuthContext.Provider value={{ auth, setAuth }}>
            {children}
        </AuthContext.Provider>
    )
}

export default AuthContext;

I want to be able to change its boolean state within an if-else instead of a button with an onCLick event in the tutorial but it shows an error in the console: setAuth is not a function

function Home() {
    
  const setAuth = useContext(AuthProvider);

  const [usernameReg, setUsernameReg] = useState("");
  const [passwordReg, setPasswordReg] = useState("");

  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  const [loginStatus, setloginStatus] = useState("");

  const uLogin = document.getElementById('userLogin');
  const pLogin = document.getElementById('passwordLogin');

  const register = () => {
    if (usernameReg === "" || passwordReg === ""){
      alert("Fields can't be blank");
      return;
    }
    Axios.post('http://localhost:3001/register', {
      username: usernameReg,
      password: passwordReg,
    }).then((response) => {
      console.log(response);
    });
  }

  const login = () => {
    Axios.post('http://localhost:3001/login', {
      username: username,
      password: password,
    }).then((response) => {
      if (response.data.message){
        setloginStatus(response.data.message);
        alert(response.data.message);
      }
      else{
        setloginStatus(response.data[0].username);
        
        
        setAuth(true);   <====================================== here


        window.location.href = "/map";
        

      }
      console.log(response.data);
    });
  }


  return (
    <div className="Home">
           
              
           <h1>Register</h1>
              <label>Username: </label>
              <input type="text"
                onChange={(e) => {
                setUsernameReg(e.target.value)
              }}/>
              <label><p></p>Password: &nbsp;</label>
              <input type="text"
                onChange={(e)=> {
                setPasswordReg(e.target.value)
              }}/>
              <p></p>
              <button onClick={register}> Register </button>
          

          <h1>--------------------------------------------------------</h1>

          {/*<form id="loginForm">*/}
            <h1>Log In</h1>
            <input id="userLogin" type="text" placeholder="Username"
              onChange={(e) => {
                setUsername(e.target.value)
              }}
            />
            <p></p>
            <input id="passwordLogin" type="password" placeholder="Password"
              onChange={(e) => {
                setPassword(e.target.value)
              }}
            />
            <p></p>
            <button  onClick={login}> Log In </button>
          {/*</form>*/}  
          

          <h1>{loginStatus}</h1>

          
    </div>
  )
}

my App.js is below

import React, { useState } from "react";
import { BrowserRouter,Route, Routes} from 'react-router-dom';
import './App.css';
import Home from "./Pages/Home";
import MapPage from "./Pages/MapPage.js";
import ProtectedRoutes from "./ProtectedRoutes";
import { AuthProvider } from "./components/AuthProvider"



function App() {

  const  [auth, setAuth ] = useState(false);
  //const [auth, setAuth] = useState(false);

  return (  
    <BrowserRouter>
      
      <Routes element ={<AuthProvider />} value={{auth, setAuth}}>
        
        <Route element ={<ProtectedRoutes />}>

            <Route element={<MapPage />} path="/map" exact/>

        </Route>

        <Route path="/" element={<Home />}/>

      </Routes>
      
    </BrowserRouter>
  );
}

export default App;

index.js below

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { AuthProvider } from './components/AuthProvider'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <AuthProvider>
    <App />
  </AuthProvider>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bitly/CRA-vitals
reportWebVitals();

I’m very new to JavaScript and I’ve only been following along tutorials for the functions or features I need for the project. Is there a way for this?

I’m also guessing that the code for the context file is overkill for a simple Boolean state.

Advertisement

Answer

You probably want to check the context docs again, and try to understand how and why you set them up, and how to access them. You tried accessing the context by passing the provider as a param to the useContext hook. This is wrong, you need to pass the Context itself. You also called the return from the context setAuth, but the return is the context itself. I urge you to read the documentation thourougly. However, this is probably what you wanted:

type AuthContextType = {
    auth: boolean;
    setAuth: Dispatch<SetStateAction<boolean>>;
};

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
    const [auth, setAuth] = useState(false);

    return (
        <AuthContext.Provider value={{ auth, setAuth }}>
            {children}
        </AuthContext.Provider>
    );
};

const useAuthContext = () => {
    const ctx = useContext(AuthContext);

    if (!ctx) throw new Error("No AuthContext Provider found");

    return ctx // as AuthContextType<...> if you need the context to be generic and to infer generics.
};

function Home() {
    const { auth, setAuth } = useAuthContext();
    ...
}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement