redux 当调用时,未知返回根状态,这可能导致不必要的重新呈现(警告)

0ejtzxu1  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(176)

当我试图转到另一个用户的个人资料页面时,我在控制台中得到一个无休止的警告,我没有得到页面,并且在页面上没有其他事情可做,所以我必须关闭它并再次打开新的自来水。


的数据
profileAction.js

import { GLOBALTYPES } from "./globalTypes";
import { getDataAPI } from "../../utils/fetchData";

export const PROFILE_TYPES = {
    LOADING: 'LOADING',
    GET_USER: 'GET_USER'
}

export const getProfileUsers = ({users, id, auth}) => async (dispatch) => {
    if(users.every(user => user._id !== id)){
        
        try {
            dispatch({type: PROFILE_TYPES.LOADING, payload: true})
            const res = await getDataAPI(`/user/${id}`, auth.token)
            console.log(res)

        } catch (err) {
            dispatch({
                type: GLOBALTYPES.ALERT, 
                payload: {error: err.response.data.msg}
            })
        }
    }
}

字符串
Info.jsx

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import Avatar from '../Avatar';
import { getProfileUsers } from '../../redux/actions/profileAction';

const Info = () => {
  const { id } = useParams()
  const { auth, profile } = useSelector(state => state);
  const dispatch = useDispatch()
  
  const [userData, setUserData] = useState([])

  useEffect(() => {
    if(id === auth.user._id){
      setUserData(auth.user)
      // console.log(userData)
    }else{
      dispatch(getProfileUsers({users: profile.users, id, auth}))
    }
  }, [id, auth.user, profile.users])

  const followed = userData.followers || []

  const follow = userData.following || []
  
  return (
        <div className='info'>
        {userData ? 
          <div className="info_container" key={userData._id}>
            <Avatar src={userData.avatar} size="supper-avatar"/>
            <div className="info_content">
              <div className="info_content_title">
                <h2>{userData.username}</h2>
                <button className="btn btn-outline-info">
                  Edit Profile
                </button>
              </div>
                <div className="follow_btn">
                  <span className="mr-4">
                    {followed.length} Followers
                  </span>
                  <span className="ml-4">
                    {follow.length} Following
                  </span>
                </div>
              <h6>{userData.fullname}</h6>
              <h6>{userData.email}</h6>
            </div>
          </div> : null
      }
    </div>
  )
}

export default Info


顺便说一句,我总是得到这个警告之前,但网页工作正常,警告并不是无休止的

62o28rlo

62o28rlo1#

当您选择“too much state”时,可能会发生这种情况,在这种情况下,您订阅了 *all * state。换句话说,任何时候 * any * state被更新,无论它是否与Info中的解构/使用有关,Info组件都会被触发重新呈现。
解决办法是缩小你选择的范围。

const auth = useSelector(state => state.auth);
const profile = useSelector(state => state.profile);

字符串
这将在任何authprofile状态值发生更改时触发Info重新呈现,但不会更改其他状态。
根据Info实际引用的代码,范围可以进一步缩小。

const user = useSelector(state => state.auth.user);
const users = useSelector(state => state.profile.users);


现在,这应该只会在userusers状态更新时触发组件重新呈现。
渲染循环问题可能与此useEffect钩子调用有关。将传递/选择的值/“派生状态”复制到本地状态是一种React反模式。userData值应该直接从当前iduser值计算。几乎任何时候你发现你已经编写了useState/useEffect耦合你真的应该使用useMemo钩子来计算(* 和memoize*)一个稳定的参考值。

const { id } = useParams();
const user = useSelector(state => state.auth.user);

const userData = useMemo(() => {
  return id === user._id ? user : null;
}, [id, user]);

useEffect(() => {
  if (id !== userData._id) {
    dispatch(getProfileUsers({ id }));
  }
}, [id, userData]);


这可以通过直接在useSelector钩子中返回计算的用户数据来进一步改进。

const { id } = useParams();
const user = useSelector(state => {
  return id === user._id ? state.auth.user : null;
});

useEffect(() => {
  if (!user) {
    dispatch(getProfileUsers({ id }));
  }
}, [id, user]);


更新getProfileUsers操作以仅使用id参数,并使用Thunk的getState函数访问存储值。这将删除其他外部依赖项。

export const getProfileUsers = ({ id }) => async (dispatch, getState) => {
  const state = getState();
  const { auth, profile: { users } } = state;

  if (users.every(user => user._id !== id)) {
    try {
      dispatch({ type: PROFILE_TYPES.LOADING, payload: true });
      const res = await getDataAPI(`/user/${id}`, auth.token);
      console.log(res);

    } catch (err) {
      dispatch({
        type: GLOBALTYPES.ALERT, 
        payload: { error: err.response.data.msg }
      });
    } finally {
      dispatch({ type: PROFILE_TYPES.LOADING, payload: false });
    }
  }
}

相关问题