javascript 当UseEffect依赖项导致无限循环时Reactredux reducer

crcmnpdw  于 2023-02-11  发布在  Java
关注(0)|答案(1)|浏览(112)

我只是在深入研究React。但是 useEffect React钩子仍然让我感到困惑。我知道我可以将依赖项作为数组传递给它来控制组件的呈现。我已经使用了props和local state来做这件事,它工作正常。
让我仍然困惑的是当我把redux reducer作为一个依赖项传递时,它会导致渲染组件的无限循环。

* 用户 * 组件

const usersComp = () => {
    const users = useSelector(state => state.users);

    useEffect(
        // Fetch users and update users state
        useDispatch().dispatch(getUsers)
    ,[users]) // <-- Causes an infinite loop!!

    if(users.length){
        return( users.map(user => <p>{user}</p>))
    }
}

getUsers还原形式转换函数

export async function getUsers(dispatch, getState) {
    fetch(endpoint)
        .then(response => response.json())
        .then(users => {
            dispatch({type: GET_USERS, payload: users})
        }).catch(err => console.error("Error: ", err));
}
* 用户 * 减速器
export default function usersReducer(state = [], action) {
    switch (action.type) {

        case GET_USERS : {
            return [...state, action.payload]
        }
    }
}

据我所知,users 一开始是一个空数组,然后被API调用的数据填充,所以 useEffect 应该触发两次;当组件刚被挂载时,以及当用户状态从API调用中改变时。那么,是什么导致了无限循环呢?

qv7cva1a

qv7cva1a1#

useEffect依赖项中删除users,因为您希望在组件挂载时获取用户,而不是每次users更改时获取用户。

useEffect(
    useDispatch().dispatch(getUsers)
,[]) // Now, it will fetch users ONLY ONCE when component is mounted

说明:

// Case 1
useEffect(() => {
  console.log("Mounted") // Printed only once when component is mounted
}, [])

// Case 2
useEffect(() => {
  console.log("users changed") // Printed each time when users is changed
}, [users])

所以,如果你在 * 案例2 * 中执行fetch,它将 * 改变 * users,这将重新触发钩子,这将再次fetch用户,这将改变users,并导致钩子重新触发→这是一个无限循环

更新:

为什么useEffect检测到state.users发生变化(在此代码中),即使state.users的值为"SAME"(相同值)?
每当调度GET_USERS操作时,reducer返回newstate({ ...state, users: action.payload })。即使action.payload的值包含相同的用户值,它也会这样做。这就是useEffect接收newusers数组的原因。(它们进行浅层比较。)
注意,[1, 2,3] is not equal to [1, 2,3][1, 2,3] === [1, 2,3]返回假。
如果出于某种原因,你想返回相同的redux状态,在reducer中执行return state,这通常是我们在reducer的switchdefault情况下所做的。

相关问题