0

I creating website with authorization. And I want to show different icons on home page, if user auth or not. But componnet render earsly then data user data changing.

For authorization I use react context.

export const UserProvider = ({children}) =>{
    const [user, setUser] = useState(getObjectCookie('user') === undefined ? null : getObjectCookie('user'))


    const signIn = async ({email, password}) =>{
        return await fetch('http://localhost:5000/user/add', {
            method: 'POST',
            body: JSON.stringify({
                email: email,
                password: password
            }),
            headers: {
                "Content-type": "application/json; charset=UTF-8"
            }
        })
            .then(res => res.json())
            .then(resultData => {
                console.log(resultData.message);
                const userData = resultData.createdUser
                setObjectCookie('user', {id: userData._id, email: userData.email}, {expires: new Date(2030, 1)})
                console.log('User\'s cookie set');
            })
            .catch(error => {
                console.log(error.message)
                return Promise.reject(error)
            })
    }
}

To check what of icon use, I check of user auth in render html

<div className="d-flex flex-pow btn-header">
    <div className=" d-flex flex-column center-elements">
        <a href="/profile">
        {user !== null ?
           <>
               <img src={require("../assets/icons/icon-profile.png")} alt="Вход" className="log-in" />
               <p>Вход</p>
           </> :
           <>
               <img src={equire("../assets/icons/header-entry.png")} alt="Вход" className="log-in" />
               <p>Вход</p>
           </>
                                
        }
        </a>
    </div>
</div>

Header if user none auth Header if user none auth

Header if user auth Header if user auth

But when I register icon not changing. I log path of action and how you can see Header render before user data is change. And I don't know how to fix this.

enter image description here

Function on register button

 const registerUser = async (e) =>{
        e.preventDefault()
        await signIn(formData)
            .then(res => {
                console.log('Its redirect');
                navigate('/')
            })
            .catch(error => console.log('SignIN error'))
    }

Auth function in ReactContext

const signIn = async ({email, password}) =>{
        return await fetch('http://localhost:5000/user/add', {
            method: 'POST',
            body: JSON.stringify({
                email: email,
                password: password
            }),
            headers: {
                "Content-type": "application/json; charset=UTF-8"
            }
        })
            .then(res => res.json())
            .then(resultData => {
                console.log(resultData.message);
                const userData = resultData.createdUser
                setObjectCookie('user', {id: userData._id, email: userData.email}, {expires: new Date(2030, 1)})
                console.log('User\'s cookie set');
            })
            .catch(error => {
                console.log(error.message)
                return Promise.reject(error)
            })
    }

I try to useState and useEffect.

const [profileIcon, setProfileIcon] = useState(user !== null ? '../assets/icons/icon-profile.png' : '../assets/icons/header-entry.png')   
    const [profileLabel, setProfileLabel] = useState(user !== null ? 'Профиль' : 'Вход')   

    console.log('Header render');

    useEffect(() =>{
        if (user !== null){
            setProfileIcon('../assets/icons/icon-profile.png')
            setProfileLabel('Профиль')
        } else{
            setProfileIcon('../assets/icons/header-entry.png')
            setProfileLabel('Вход')
        }
    }, [user])

    const undottedUL = {
        "listStyleType": "none"
    }

1 Answers1

-1

Not sure it will fix the issue but you can simplify the code by removing the useEffect altogether. Replace with derived state:

const profileLabel = user !== null ? 'Профиль' : 'Вход';  

Edited to show useMemo based on comments:

 const profile = useMemo(() => {
    if (user) {
      return {
        icon: '../assets/icons/icon-profile.png',
        label:'Профиль'
      };
    }
    return {
      icon: '../assets/icons/header-entry.png',
      label:'Вход'
    };
  }, [user]);
  • Maybe I'm not understand your idea, but user data update later than header component render. I use this condition in html code yet, but user data is not correct, because of that I tried useEffect – Roman Nichi May 26 '23 at 08:53
  • By doing that `profileLabel` will be recalculated on each rerender, that is not a good way to do it. It is possible with `useMemo` though – Florent M. May 26 '23 at 08:53
  • @FlorentM. I'm bad know how work useMemo, but it calculate data between rerenders. In my situation header don't rernder, it render one time until user data is updating – Roman Nichi May 26 '23 at 08:58
  • From what I have read, useMemo and useCallback should only be used to avoid a performance hit from rerendering. React by design rerenders basically everything and most trivial prop rerenders have no affect on performance. Regardless, I was just pointing out that useEffect is not the correct route and derived state would be easier (with or without useMemo). :) – TomColabHealth May 26 '23 at 09:16