skip to Main Content

When I’m trying to update user details through a modal, the page where user details are gets blank. I have to reload the browser to load the user page.

User.js ->

import React, { useContext, useState, useEffect } from 'react'
import noteContext from '../context/notes/noteContext';
import { useNavigate } from 'react-router-dom';
import Useritem from './Useritem';


const User = (props) => {

    const context = useContext(noteContext);
    const { fetchUser, editUser, deleteUser } = context;
    const { showalert } = props;
    const [modal, setModal] = useState(false)
    const [check, setCheck] = useState(false)
    const [deletemodal, setDeletemodal] = useState(false)
    const [delete_user, setDeleteuser] = useState({ id: "" })
    let navigate = useNavigate();

    useEffect(() => {
        if (localStorage.getItem('token')) {
            fetchUser();
        }
        else {
            showalert("Login to see your details", "danger");
            navigate('/login')
        }
        // eslint-disable-next-line
    }, [])

    const [newUser, setNewuser] = useState({ id: "", username: "", lastname: "", age: "", email: "", password: "", change_password: "" })

    const updateNote = (currentUser) => {
        setModal(true);
        setNewuser({ id: currentUser._id, username: currentUser.name, lastname: currentUser.lastname, age: currentUser.age, email: currentUser.email, password: "", change_password: "" })
    }

    const deleteConfirm = (user_id) => {
        setDeletemodal(true)
        setDeleteuser({ id: user_id })
    }

    const handleDelete = (e) => {
        deleteUser(delete_user.id);
        setDeletemodal(false);
        navigate('/login');
    }

    const handleClick = (e) => {
        e.preventDefault();
        editUser(newUser.id, newUser.username, newUser.lastname, newUser.age, newUser.password, newUser.change_password);
        window.location.reload(); //I had to use this so that when i click on update the page get reload
    }
    const onChange = (e) => {
        setNewuser({ ...newUser, [e.target.name]: e.target.value })
    }


    return (
        <div>
            {/* Update user Modal */}
            <div className={`${modal ? '' : 'hidden'} relative z-10`} aria-labelledby="modal-title" role="dialog" aria-modal="true">



                <div className="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
                    <div className="">
                        <div className="mx-auto flex h-12 w-auto justify-between   sm:mx-0 sm:h-10 ">
                            <button onClick={() => setModal(!modal)} >X</button>
                        </div>
                        <div className="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
                            <h3 className="text-base font-semibold leading-6 text-gray-900" id="modal-title">Update your details {newUser.id}</h3>
                            <div className="mt-2">
                                <form>

                                    <input type="text" id="username" name="username" value={newUser.username} onChange={onChange} minLength={5} required />
                                    <input type="text" id="lastname" name="lastname" value={newUser.lastname} onChange={onChange} minLength={5} required />
                                    <input type="number" id="age" name="age" value={newUser.age} onChange={onChange} minLength={5} required />
                                    <input disabled type="text" id="email" name="email" value={newUser.email} onChange={onChange} minLength={5} required />
                                    <input onClick={() => setCheck(!check)} type="checkbox" role="switch" id="flexSwitchCheckDefault" />
                                    <input disabled={check ? false : true} type="text" id="password" name="password" value={newUser.password} onChange={onChange} />
                                    <input disabled={check ? false : true} type="text" id="change_password" name="change_password" value={newUser.change_password} onChange={onChange} />
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
                    <button onClick={handleClick} type="button" >Update</button>
                    <button onClick={() => setModal(!modal)} type="button" >Cancel</button>
                </div>
            </div>
            {/* End of Update user Modal */}

            {/* Delete user modal */}
            <div className={`${deletemodal ? '' : 'hidden'} relative z-10`} aria-labelledby="modal-title" role="dialog" aria-modal="true">

                <div >
                    <div className="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
                        <div className="">
                            <div className="mx-auto flex h-12 w-auto justify-between   sm:mx-0 sm:h-10 ">
                                <button onClick={() => setDeletemodal(!deletemodal)} >X</button>
                            </div>
                            <div className="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
                                <h3 className="text-base font-semibold leading-6 text-gray-900" id="modal-title">Are you sure you want to delete your account?</h3>

                            </div>
                        </div>
                    </div>
                    <div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
                        <button onClick={handleDelete} type="button" >Delete</button>
                        <button onClick={() => setDeletemodal(!deletemodal)} type="button" >Cancel</button>
                    </div>
                </div>
            </div>
            {/* End of Delete user Modal */}

            <div>
                <Useritem updateNote={updateNote} deleteConfirm={deleteConfirm} />
            </div>
        </div>
    )
}

export default User

UserItem.js ->

import React,{useEffect, useContext} from 'react'
import noteContext from '../context/notes/noteContext';
import { useNavigate } from "react-router-dom";



const Useritem = (props) => {

    const { updateNote, deleteConfirm } = props;
    const context = useContext(noteContext);
    const { userdetail } = context;

    let navigate = useNavigate();
    
    useEffect(() => {
        if (!localStorage.getItem("token")) {
            navigate('/login');
        }
        // eslint-disable-next-line
    }, [])
    
    const userData = userdetail.user;
  
    return (
        <div>
            {/* ----------------- user page ------------ */}

            {userData && <div className="p-16">
                <div className="p-8 bg-white shadow mt-24">
                    <div className="grid grid-cols-1 md:grid-cols-3">
                        <div className="grid grid-cols-3 text-center order-last md:order-first mt-20 md:mt-0">
                            <div>
                                <p className="font-bold text-gray-700 text-xl">{detail.countNotes}</p>
                                <p className="text-gray-400">Total Notes</p>
                            </div>
                            <div>
                                <p className="font-bold text-gray-700 text-xl">{userData._id}</p>
                                <p className="text-gray-400">ID</p>
                            </div>
                        </div>
                        
                        <div className="space-x-8 flex justify-between mt-32 md:mt-0 md:justify-center">
                            <button onClick={() => { updateNote(userData) }}>
                                Edit
                            </button>
                            <button onClick={() => { deleteConfirm(userData._id) }} >
                                Deactivate
                            </button>
                        </div>
                    </div>
                    <div className="mt-20 text-center border-b pb-12">
                        <h1 className="text-4xl font-medium text-gray-700">
                            {userData.name}, <span className="font-light text-gray-500">{userData.age}</span>
                        </h1>
                        <p className="font-light text-gray-600 mt-3">{userData.lastname}, {userData.name}</p>
                        <p className="mt-8 text-gray-500">
                            Email - {userData.email}
                        </p>
                    </div>
                    
                </div>
            </div>}
        </div>
    )
}

export default Useritem

NoteState.js ->

import React, { useState } from "react";
import NoteContext from "./noteContext"; 

const NoteState = (props) => {

    const host = 'http://127.0.0.1:5000';
   
    const authToken = localStorage.getItem('token');
    
    const [userdetail, setUserdetail] = useState('')

    //Fetch User
    const fetchUser = async () => {
        const response = await fetch(`${host}/api/auth/getuser`, {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
                "auth-token": authToken
            },
        });
        const json = await response.json(); 
        setUserdetail(json);
    }

    // Update user
    const editUser = async (id, name, lastname, age, password, newPassword) => {
        //API call
        const response = await fetch(`${host}/api/auth/updateuser/${id}`, {
            method: "PUT",
            headers: {
                "Content-Type": "application/json",
                "auth-token": authToken
            },

            body: JSON.stringify({ name, lastname, age, password, newPassword }), 
        });
        const json = await response.json();
        console.log(json)

        let updatedUser = JSON.parse(JSON.stringify(userdetail))
       
        console.log(updatedUser);

        if (updatedUser._id === id) {
            updatedUser.name = name;
            updatedUser.lastname = lastname;
            updatedUser.age = age;
            updatedUser.password = newPassword;
            
        }

        console.log(updatedUser);

        if (json.success) {
            props.showalert(`${json.message}`, 'success');
            console.log(json.message)
        } else {
            if (json.message === undefined) {
                props.showalert(`Oops unable to update your details`, 'danger');
                console.log(json.message + 'Unable to update your details')
            } else {
                props.showalert(`${json.message}`, 'danger');
                console.log(json.message)
            }
        }
        setUserdetail(updatedUser)
    }


    return (
       
        <NoteContext.Provider value={{ fetchUser, userdetail, editUser, deleteUser }}>
            {props.children}
        </NoteContext.Provider>
    )
}


export default NoteState;



NoteContext.js ->

import { createContext } from "react";
const noteContext = createContext();
export default noteContext;

App.js ->

import { BrowserRouter, Route, Routes } from "react-router-dom";
import Navbar from './components/Navbar';
import Home from './components/Home';
import About from './components/About';
import NoteState from "./context/notes/NoteState";
import './App.css';
import Alerts from "./components/Alerts";
import Login from "./components/Login";
import Singup from "./components/Singup";
import { useState } from "react";
import User from "./components/User";


// TODO use context API for ALERT

function App() {

  const [alert, setAlert] = useState(null);

  const showalert = (message, type) => {
    setAlert({
      msg: message,
      type: type
    })
    setTimeout(()=>{
      setAlert(null);
    },2000)
  }

  return (
    <NoteState showalert={showalert}>
      <BrowserRouter>

        <Navbar showalert={showalert}/>
        <div className="">
        <Alerts alert={alert} />
          <Routes>

            <Route exact path='/' element={<Home showalert={showalert} />} />
            <Route exact path='/login' element={<Login showalert={showalert}/>} />
            <Route exact path='/singup' element={<Singup showalert={showalert}/>} />
            <Route exact path='/user' element={<User showalert={showalert}/>} />

          </Routes>
        </div>
      </BrowserRouter>
    </NoteState>
  );
}

export default App;

I have updated my code a little bit from reading comments. Now the page doesnt vanish. But to display the updated data i have to reload the page.

Below are the snip of what’s happing ->

Initial image of user page

Updating details

After click update

After reloading page

I’m also displaying message from the function where logs are coming from. Hope it helps
Console log image

image after updating

3

Answers


  1. Chosen as BEST ANSWER

    Hi thanks all for your suggestion, I noticed what was wrong in my code.

    My state was not getting updated in NoteState.js in edit(), So i did this ->

    `

    let updatedUser = JSON.parse(JSON.stringify(json))
    updatedUser = updatedUser.user;
    if (updatedUser._id === id) {
    
        let newupdatedUser = {
            ...userdetail,
            user: {
                ...userdetail.user,
                name: updatedUser.name,
                lastname: updatedUser.lastname,
                age: updatedUser.age
            }
        };
    
        setUserdetail(newupdatedUser);
    }
    

    `

    Its working now. Also please let me know if its the correct way to update the state.


  2. Your types are off.

    • UserItem expects userDetail from the context to be an object (with user and countNotes properties). So this must also be the type returned by the GET endpoint.
    • After PUT request we write notes/updatedUser to userDetail which is assumed to be an array according to the code.

    After reviewing the logs, I believe the error is that UserItem gets passed an array as detail which means userData = detail.user // == undefined and hence the UserItem component won’t render. Since we have {userData &&.

    Login or Signup to reply.
  3. Add the newUser dependency in useEffect your problem every time you update use the newUser state values also updating then just make reload the component then so it shows the updatedUserData

    useEffect(() => {
            if (localStorage.getItem('token')) {
                fetchUser();
            }
            else {
                showalert("Login to see your details", "danger");
                navigate('/login')
            }
            // eslint-disable-next-line
        }, [newUser])
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search