首页 > 解决方案 > React redux - 刷新页面不使用useEffect设置Form数据

问题描述

当我在主页上单击“个人资料”时,这会将我带到“个人资料页面”组件,并且表单输入由之前已经存储在“用户”redux 状态中的数据填充。当我刷新页面时,所有输入都变为空白,尽管调度了“loadOrCreateUser”(这让我从后端获取了当前用户)并在 useEffect 挂钩中设置了表单数据。

页面刷新后,我检查了 redux 状态,“用户”状态确实有用户的信息,但表单数据没有设置。这真的很奇怪,因为刷新后,来自 useSelector 的“用户”变得无法识别,但“用户”redux 状态有数据。

Profile.js 组件

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

标签: reactjsreact-redux

解决方案


问题是在页面刷新后在 useEffect 中调度“loadOrCreateUser”时,下一次调用“setFormData”时该操作尚未完成。

为了解决这个问题,我添加了另一个名为 isDone 的状态,当“loadOrCreateUser”操作完成时,它设置为 true(在它自己的 reducer 中),如下所示:

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
    });  
  }
}

然后在 Profile.js 中,我添加了:

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

并在 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])

推荐阅读