Home > Enterprise >  Why is the entry in the state deleted?
Why is the entry in the state deleted?

Time:11-30

I tried to do something very simple but I do not understand why it not working for me

so i have a component that include the details about the user are logged in and i want to request the details user and put them in the component

so I do a axios.get to my back-end i get the detail set them in the state with success put them in the component but when I refresh the page i get state is undefined

I add here the code

import axios from "axios";
import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from 'react-router-dom'
import './account.css'



function Account(props) {

    const [user, setUser] = useState()
    const [currentPass, setCurrentPass] = useState()
    const [newPass, setNewPass] = useState()
    const [confirmPass, setConfirmPass] = useState()



    let navigate = useNavigate();

    useEffect(() => {
        let userArr = []
        try {
            axios.create({ withCredentials: true }).get(`http://127.0.0.1:3000/users/getMe`)
                .then(res => {
                    console.log(res.data.data.user) //object
                    userArr.push(res.data.data.user)
                    console.log(userArr)
                    setUser(userArr)
                    console.log(user)
                })

        } catch (error) {
            console.log(error)
        }
    }, [])

    const updatePassword = async (e) => {
        e.preventDefault()
        try {
            const res = await axios.create({ withCredentials: true }).patch(`http://127.0.0.1:3000/users/updatePassword`, {
                currentPassword: currentPass,
                newPassword: newPass,
                passwordConfirm: confirmPass
            });
            if (!res) {
                return "not work"

            }
            console.log(res.data.data.user)
            navigate("/", { replace: true });
        } catch (error) {
            console.log(error);
        }
    }



    return (
        <div className="account-container" >
            <div className="title-container">
                <p className="title">My Account</p>
            </div>
            <p className="sub-title">User information </p>
            <form className="form-user-information">
                <div className="div-form-user-information">
                    <label className="label-form-user-information">Username</label>
                    <textarea placeholder="Username..." />
                </div>
                <div className="div-form-user-information">
                    <label className="label-form-user-information">ssss</label>
                    <textarea placeholder={user.map(el => {
                        return el.email
                    })} />
                </div>
                <div className="div-form-user-information">
                    <label className="label-form-user-information">First name</label>
                    <textarea placeholder="First name..." />
                </div>
                <div className="div-form-user-information">
                    <label className="label-form-user-information">Last name</label>
                    <textarea placeholder="Last name..." />
                </div>
            </form>
            <div className="buttom-line"></div>
            {/* //////CONTACT INFORMATION////////// */}
            <p className="sub-title-contact">CONTACT INFORMATION </p>
            <form className="form-contact-information">
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">Full Address</label>
                    <textarea placeholder="Full Address..." />
                </div>
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">City</label>
                    <textarea placeholder="City..." />
                </div>
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">Country</label>
                    <textarea placeholder="Country..." />
                </div>
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">Postal code</label>
                    <textarea placeholder="Postal code..." />
                </div>
            </form>
            <div className="buttom-line-contact"></div>
            {/* //////PASSWORD INFORMATION////////// */}
            <p className="sub-title-password">UPDATE PASSWORD </p>
            <form className="form-password-information">
                <div className="div-form-password-information">
                    <label className="label-form-password-information">Current Password</label>
                    <textarea onChange={(e) => setCurrentPass(e.target.value)} placeholder="Current Password..." />
                </div>
                <div className="div-form-password-information">
                    <label className="label-form-password-information">New Password</label>
                    <textarea onChange={(e) => setNewPass(e.target.value)} placeholder="New Password..." />
                </div>
                <div className="div-form-password-information">
                    <label className="label-form-password-information">Confirm Password</label>
                    <textarea onChange={(e) => setConfirmPass(e.target.value)} placeholder="Confirm Password..." />
                </div>
                <button onClick={(e) => updatePassword(e)} className="btn-update-pass">Update password</button>
            </form>
        </div>
    );
}

export default Account;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

CodePudding user response:

maybe the state is not filled when the app is rendered. Try waiting for the axios request by adding a little loading system:

import axios from "axios";
import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from 'react-router-dom'
import './account.css'



function Account(props) {

    const [user, setUser] = useState()
    const [currentPass, setCurrentPass] = useState()
    const [newPass, setNewPass] = useState()
    const [confirmPass, setConfirmPass] = useState()
    const [loading, setLoading] = useState(true) // add this



    let navigate = useNavigate();

    useEffect(() => {
        let userArr = []
        try {
            axios.create({ withCredentials: true }).get(`http://127.0.0.1:3000/users/getMe`)
                .then(res => {
                    console.log(res.data.data.user) //object
                    userArr.push(res.data.data.user)
                    console.log(userArr)
                    setUser(userArr)
                    console.log(user)
                    setLoading(false) // and this
                })

        } catch (error) {
            console.log(error)
        }
    }, [])

    const updatePassword = async (e) => {
        e.preventDefault()
        try {
            const res = await axios.create({ withCredentials: true }).patch(`http://127.0.0.1:3000/users/updatePassword`, {
                currentPassword: currentPass,
                newPassword: newPass,
                passwordConfirm: confirmPass
            });
            if (!res) {
                return "not work"

            }
            console.log(res.data.data.user)
            navigate("/", { replace: true });
        } catch (error) {
            console.log(error);
        }
    }


    if(loading) return <p>loading</p> //and this...
    return (
        <div className="account-container" >
            <div className="title-container">
                <p className="title">My Account</p>
            </div>
            <p className="sub-title">User information </p>
            <form className="form-user-information">
                <div className="div-form-user-information">
                    <label className="label-form-user-information">Username</label>
                    <textarea placeholder="Username..." />
                </div>
                <div className="div-form-user-information">
                    <label className="label-form-user-information">ssss</label>
                    <textarea placeholder={user.map(el => {
                        return el.email
                    })} />
                </div>
                <div className="div-form-user-information">
                    <label className="label-form-user-information">First name</label>
                    <textarea placeholder="First name..." />
                </div>
                <div className="div-form-user-information">
                    <label className="label-form-user-information">Last name</label>
                    <textarea placeholder="Last name..." />
                </div>
            </form>
            <div className="buttom-line"></div>
            {/* //////CONTACT INFORMATION////////// */}
            <p className="sub-title-contact">CONTACT INFORMATION </p>
            <form className="form-contact-information">
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">Full Address</label>
                    <textarea placeholder="Full Address..." />
                </div>
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">City</label>
                    <textarea placeholder="City..." />
                </div>
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">Country</label>
                    <textarea placeholder="Country..." />
                </div>
                <div className="div-form-contact-information">
                    <label className="label-form-contact-information">Postal code</label>
                    <textarea placeholder="Postal code..." />
                </div>
            </form>
            <div className="buttom-line-contact"></div>
            {/* //////PASSWORD INFORMATION////////// */}
            <p className="sub-title-password">UPDATE PASSWORD </p>
            <form className="form-password-information">
                <div className="div-form-password-information">
                    <label className="label-form-password-information">Current Password</label>
                    <textarea onChange={(e) => setCurrentPass(e.target.value)} placeholder="Current Password..." />
                </div>
                <div className="div-form-password-information">
                    <label className="label-form-password-information">New Password</label>
                    <textarea onChange={(e) => setNewPass(e.target.value)} placeholder="New Password..." />
                </div>
                <div className="div-form-password-information">
                    <label className="label-form-password-information">Confirm Password</label>
                    <textarea onChange={(e) => setConfirmPass(e.target.value)} placeholder="Confirm Password..." />
                </div>
                <button onClick={(e) => updatePassword(e)} className="btn-update-pass">Update password</button>
            </form>
        </div>
    );
}

export default Account;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

CodePudding user response:

Based on your post and comment, the issue seems to be that you are trying to access the value of the user state property before it is populated by the async axios call.

This is a common occurrence in React, and is quite simple to solve via conditional rendering.

Example:

{user === undefined
   ? <></> 
   : <textarea placeholder={user.map(el => {
        return el.email
     })} />
}

Or, instead of an empty fragment, you can put a loader/spinner or any other UI you'd like, in-order to let the user know that something is loading.

If you have more places where you try to access the value of user, you can use the conditional rendering there as-well.

Alternativaly, like Matias mentioned, you can put the condition before the "main" return of the component.
This is useful if you have multiple places where you need to access the value of user and you don't want to copy this logic for all of them.

Example:

if (user === undefined) {
   return <></>
}
return (
   ...
)
  • Related