0

I have a basic React project to learn useContext and i cant get the state to update.

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import { AuthProvider } from './Contexts/AuthProvider';

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

App.js

import { Routes, Route, Link } from 'react-router-dom';
import Navigation from './Pages/Navigation';
import Home from './Pages/Home';
import Login from './Pages/Login';
import Profile from './Pages/Profile';
import Dashboard from './Pages/Dashboard';
import NoMatch from './Pages/NoMatch';
import ProtectedRoute from './Pages/ProtectedRoute';

function App() {

  return (
    <div>
      <Navigation />

      <Routes>
        <Route index element={<Home />} />
        <Route path='login' element={<Login />} />
        <Route path="home" element={<Home />} />
        <Route path="Profile" element={<ProtectedRoute><Profile /></ProtectedRoute>} />
        <Route path="Dashboard" element={<Dashboard />} />
        <Route path="*" element={<NoMatch />} />
      </Routes>
    </div >
  );
}

export default App;

AuthProvider.js

import { createContext, useState } from "react";

const AuthContext = createContext({});

export const AuthProvider = ({ children }) => {

    const [user, setUser] = useState({ username: '', password: '', isAuthenticated: false });

    const login = (_username, _password) => {
        console.log('inside ' + _username);
        console.log('inside ' + _password);
        setUser({ username: _username, password: _password, isAuthenticated: true });
        console.log(user);
    }

    const logout = () => {
        setUser({ username: '', password: '', isAuthenticated: false });
    }

    return (
        <AuthContext.Provider value={[user, login, logout, setUser]}>
            {children}
        </AuthContext.Provider>
    );

};

export default AuthContext;

login.js

import { useState, useContext } from "react";
import { Link } from "react-router-dom";
import AuthContext from '../Contexts/AuthProvider';

const Login = () => {

    const [user, login, logout, setUser] = useContext(AuthContext)

    const [username, usernameupdate] = useState('');
    const [password, passwordupdate] = useState('');

    const handlesubmit = (e) => {
        e.preventDefault();
        console.log(username);
        console.log(password);
        login(username, password);
        console.log(user);
    }

    return (
        <div>
            <form className="container" onSubmit={handlesubmit}>
                <div className="card">
                    <div className="card-header">
                        <h2>User Login</h2>
                    </div>
                    <div className="card-body">
                        <div className="form-group">
                            <label>User Name <span className="errmsg">*</span></label>
                            <input value={username} onChange={e => usernameupdate(e.target.value)} className="form-control"></input>
                        </div>
                        <div className="form-group">
                            <label>Password <span className="errmsg">*</span></label>
                            <input type="password" value={password} onChange={e => passwordupdate(e.target.value)} className="form-control"></input>
                        </div>
                    </div>
                    <div className="card-footer">
                        <button type="submit" className="btn btn-primary">Login</button>
                        <Link className="btn btn-success" to={'/register'}>New User</Link>
                    </div>
                </div>
            </form>
        </div>
    )
}

export default Login;

When i enter the name and password and submit the values reach the "console.log' inside the function login but the user is not updated and stays as the blank entries one.

Where am i going wrong in this?

Thanks

andythpa
  • 21
  • 1
  • 4
  • `console.log(user);` Are these `console.log`s the reason you think it's not working? These can only ever log out the old value – Nicholas Tower Jul 25 '23 at 19:47
  • Yes they only seem to output the original value for User (username: '', password: '', isAuthenticated: false) – andythpa Jul 26 '23 at 06:16
  • That sounds completely normal. Calling `setState` does not (and can not) change the value in your local variables. It just asks react to render the component again. That new render will have the new values, but code in the old render does not. See this [stack overflow](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately) or this part of [react's documentation](https://react.dev/reference/react/useState#ive-updated-the-state-but-logging-gives-me-the-old-value) – Nicholas Tower Jul 26 '23 at 13:02

1 Answers1

0

probably your console.log is not keeping up with the state update, please try putting the following code on the login screen:

useEffect(() => console.log(user), [user]);

Keep in mind that this will only be to see the state update; after that you can remove this code as it is not needed for the functionality of the code.

  • Thanks @paulo-victor adding that worked. I'm just not sure why its not on the online tutorials and i also did an earlier project of similar structure calling an API for user verification but protected routes and it did update the "user" without the need for useEffect. – andythpa Jul 26 '23 at 18:20
  • Hi, I'm still getting problems where when i navigate to other pages the "User" does not maintain its values and any protected pages are logged out – andythpa Aug 02 '23 at 19:13