热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用`useSelector`选择器在分派操作后未能实时更新状态

在使用`useSelector`选择器时,发现分派操作后状态未能实时更新。这可能是由于React组件的渲染机制或Redux的状态管理问题导致的。建议检查`useSelector`的依赖项和`dispatch`的调用时机,确保状态变化能够正确触发组件重新渲染。此外,可以考虑使用`useEffect`钩子来监听状态变化,以确保及时更新。

这里是Codesandbox。

getIDs()更新cellsinitializeCells()然后需要。但是,此更改在分派操作后不会反映出来。尽管如此,我仍然可以在Redux dev tools上看到该操作已通过,并且cells的值已相应更改。 gameStart()通过props传递到子组件cells,并通过useEffect()钩子在那里调用。我需要传递一个空数组作为该钩子的第二个参数,否则它将永远运行,因为每次调用时状态都会更新。问题在于,getIDs()首次运行后,新状态不适用于以下功能。 gameStart()似乎已经完全完成并再次被调用。我需要声明initializeCells()完成后立即更新getIDs()的状态。

cells.js

import React,{ useEffect } from "react";
import { useSelector } from "react-redux";
import Cell from "./Container/Container/Cell";
const Cells = props => {
const board = useSelector(state => state.board);
useEffect(() => {
props.gameStart();
},[]);
return (


{board.map(cell => {
return (
id={cell.id.substring(1)}
key={cell.id.substring(1)}
classname="cell"
/>
);
})}

);
};
export default Cells;

app.js

import React,{ useEffect } from "react";
import { useSelector,useDispatch } from "react-redux";
import {
setCells,setBoard
} from "../../redux/actions/index";
const Game = () => {
const dispatch = useDispatch();
const cells = useSelector(state => state.cells);
const board = useSelector(state => state.board);
const boardSize = useSelector(state => state.boardSize);
async function gameStart() {
await getIDs();
console.log(cells); // []
await initializeCells();
await assignsnake();
await placeFood();
await paintCells();
}
function getIDs() {
let cellID = "";
let collection = [];
for (let i = 1; i <= boardSize.rows; i++) {
for (let j = 1; j <= boardSize.columns; j++) {
cellID = `#cell-${i}-${j}`;
collection.push(cellID);
}
}
dispatch(setCells(collection));
console.log(cells); // []
}
function initializeCells() {
console.log(cells); // []
const board = [];
// for loop never runs because cells is empty
for (let i = 0; i board.push(cell(cells[i]));
}
dispatch(setBoard(board));
console.log("Board: ",board); // []
}
function cell(id) {
return {
id: id,row: id.match("-(.*)-")[1],column: id.substr(id.lastIndexOf("-") + 1),hasFood: false,hassnake: false
};
}
return (
...
)
}
export default Game;

reducers / index.js

import {
SET_CELLS,SET_BOARD
} from "../constants/action-types";
const initialState = {
board: [],cells: [],boardSize: {
rows: 25,columns: 40
}
};
const rootReducer = (state = initialState,action) => {
switch (action.type) {
case SET_CELLS:
return Object.assign({},state,{
cells: action.payload
});
case SET_BOARD:
return Object.assign({},{
board: action.payload
});
default:
return state;
}
};

actions / index.js

import {
SET_CELLS,SET_BOARD
} from "../constants/action-types";
export const setCells = payload => {
return { type: SET_CELLS,payload };
};
export const setBoard = payload => {
return { type: SET_BOARD,payload };
};

constants / action-types.js

export const SET_CELLS = "SET_CELLS";
export const SET_BOARD = "SET_BOARD";



我建议您在这里重新考虑所有的模式,并在编写代码之前考虑一下可以通知您的决定的内容。首先,为什么要这样设置状态?如果使用状态是合理的,那么当您仅在cells组件中访问board时,为什么要创建单独的boardCells状态值?是否会控制诸如boardSize之类的任何值?也许在应用加载时会从远程网络资源中调用它们,而您不立即知道它们吗?如果这两个都不对,则没有任何充分的理由将它们存储在状态中,它们可以只是在组件外部初始化时声明的常量。如果是,则代码应适合用例。如果要由用户控制电路板的尺寸,则应使用默认值初始化值,并处理所有同步状态更改,而在reducer内没有副作用。

此外,正如您所知,使用异步函数的方式有点像反模式。使用Redux,如果您使用的是真正的异步功能,即调用网络资源,则可以使用thunks,并在每次{{ 1}}。

否则,您是否熟悉getState()的类组件生命周期模式?本质上,您“监听”状态更改,并且仅在状态更改后调用依赖于状态更改的函数。您可以使用钩子执行此操作的一种方法是dispatch使用包含您所依赖状态的依赖项数组,这意味着只有在这些依赖项发生更改时才会调用它,并且您可以在{中进行进一步的条件检查{1}}函数(但从不有条件地包装componentDidUpdate!)。当使用对象或数组作为依赖项时,事情变得更加复杂,因为它使用严格的相等性检查,因此您可能需要使用ref并比较useEffect中的当前值和先前值,以及类似{{3} }。

所有这些,在您当前的用例中,您不需要执行任何操作,因为您只是在同步初始化静态值。如果useEffect值不受控制,我个人甚至不会将其存储在状态中,但是出于教育的目的,这是您在化简器中的操作方式。

首先,只需使用useEffect组件中的useEffect

然后,将所有同步逻辑封装在减速器中:

boardSize
,

在分派一些动作后,仅在下一次渲染时才会提供更新的存储。对于具有钩子和带有_m HOC的类的函数,这是相同的。

您需要更改代码,以免立即发生更改。对于我来说,很难理解您的意图,您可能首先要渲染它的来龙去脉,并采取行动来分而忘却。而且应该可以。

如果不这样做,请进行最少的采样(仅使用相关的钩子+数据呈现方式),并描述您要获取的内容(而不是“如何”)


推荐阅读
author-avatar
路过然后错过
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有