0

When I click "Profile" on my homepage, this takes me to the "Profile page" component and the form inputs get populated by data that is already stored in the "user" redux state from before. When I refresh the page, all the inputs become blank, despite dispatching the "loadOrCreateUser" (which gets me the current user from the backend) and setting the form data in the useEffect hook.

After the page refresh, I checked the redux state, and the "user" state does in fact have the user's info in it, yet the form data did not get set. It's really odd, since after the refresh, the "user" from useSelector becomes unidentified, yet the "user" redux state has data.

Profile.js component

import React from 'react'
import { Link, Redirect } from 'react-router-dom'
import { useState, useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { loadOrCreateUser, updateUser } from '../../state/action-creators/authActions'

const Profile = () => {
  const dispatch = useDispatch();
  const user = useSelector(state => state.auth.user);
  const [filedCheck, setFieldCheck] = useState(false);
  const [formData, setFormData] = useState({
    username: "",
    email: "",
    first_name: "",
    last_name: "",
    about: "",
    password: ""
  });

  const {username, email, first_name, last_name, about, password} = formData;

  useEffect(() => {
    formData.password !== '' ? setFieldCheck(false) : setFieldCheck(true);

  }, [formData.password])


  useEffect(async() => {
    await dispatch(loadOrCreateUser());

    setFormData({
      ...formData, 
      username: user.username,
      email: user.email,
      first_name: user.first_name,
      last_name: user.last_name,
      about: user.about
    });

  }, [])


  const onChange = e => setFormData({
    ...formData, [e.target.name]: e.target.value
  }); 

  const onSubmit = e => {
    e.preventDefault();
    const data = {
      username,
      email,
      first_name,
      last_name,
      about,
      password
    };
    dispatch(updateUser(data));
  }

  return (
    // Form inputs...

  )
}

export default Profile
Luka Reeson
  • 113
  • 12
  • Does this answer your question? [How to trigger off callback after updating state in Redux?](https://stackoverflow.com/questions/39524855/how-to-trigger-off-callback-after-updating-state-in-redux) – Terminat Sep 03 '21 at 13:22
  • Not really. It says I should add input to the useEffect. In my case that would be "user", so when it changes this should trigger the useEffect. But if I do that and hit refresh, the form data does get set, but the useEffect gets stuck in an infinite loop... – Luka Reeson Sep 03 '21 at 15:28

1 Answers1

0

The problem was that when dispatching "loadOrCreateUser" in useEffect after page refresh, the action is not yet finished when "setFormData" is called next.

To resolve this issue, I've added another state called isDone, which is set to true (in its own reducer) when "loadOrCreateUser" action is finished like so:

export const loadOrCreateUser = () => async (dispatch, getState) => {
  try {
    const res = await axios.get('/api/auth/get-or-create-user/', tokenConfig(getState));

    dispatch({
      type: GET_OR_CREATE_USER,
      payload: res.data
    })

    dispatch({
      type: UPDATE_DONE
    })

  } catch(err) {
    localStorage.removeItem('token');
    await axios.delete('/api/clear-session/', null);
    dispatch({
      type: AUTH_ERROR
    });
    dispatch({
      type: RELOAD
    });  
  }
}

Then in the Profile.js, I've added:

const isDone = useSelector(state => state.utils.isDone)

and used it in useEffect:

  useEffect(() => {
    dispatch(loadOrCreateUser());

    user && setFormData({
      ...formData, 
      username: user.username,
      email: user.email,
      first_name: user.first_name,
      last_name: user.last_name,
      about: user.about
    });

  }, [isDone])
Luka Reeson
  • 113
  • 12