javascript - 延迟的 redux 调度调用加速 UI 更新
问题描述
我正在尝试在 ReactJs、Redux 和 TS 中创建一个简单的块堆叠游戏。我想无限地从左到右移动堆栈中的顶行,直到按下 Space 或 Enter 键。首先,当 UI 加载时它工作正常,但在它开始加速 UI 更新后不久就会出现不一致的更新。像这样...
我想在延迟 200 毫秒后每次渲染将位置更新 1 步。
我正在尝试这样做。
useEffect(() => {
if (play) {
setTimeout(() => {
moveStackLine(JSON.parse(JSON.stringify(data)), direction);
}, 200);
}
});
moveStackLine 函数:
const moveStackLine = useCallback((_data: GameData, directionCopy: 'left' | 'right') => {
console.log('_data1', _data);
let _direction = directionCopy;
const lastIndexData = _data[_data.length - 1];
if (_direction === 'right' && lastIndexData[1] < gameWidth) {
lastIndexData[0] += 1;
lastIndexData[1] += 1;
}
if (_direction === 'left' && lastIndexData[0] > 0) {
lastIndexData[0] -= 1;
lastIndexData[1] -= 1;
}
if (lastIndexData[1] === gameWidth - 1) {
_direction = 'left';
} else if (lastIndexData[0] === 0) {
_direction = 'right';
}
_data.splice(_data.length - 1, 1, lastIndexData);
dispatch({ type: ACTIONS.CHANGE_ACTIVE_LINE_START_END_POS, payload: _data });
if (_direction !== directionCopy) {
dispatch({ type: ACTIONS.CHANGE_DIRECTION, payload: _direction });
}
}, [dispatch, gameWidth]);
上面的函数改变了我的 rootState 中数据数组的开始和结束位置。
初始状态:
export const gameState: InitialGameState = {
currentLine: 0,
gameWidth: 16,
gameHeight: 20,
direction: 'right',
play: true,
data: [[2, 5], [0, 3], [4, 7]],
}
data 数组中的每个数组代表一条线以及该线的开始和结束位置。
我的渲染逻辑看起来像这样。
const renderLine = (startEndIndex: Array<number>) => {
const columns = [];
for (let j = 0; j < gameWidth; j++) {
columns.push(
<div className={cx(styles.ball, { [styles.active]: j >= startEndIndex[0] && j <= startEndIndex[1] })}></div>
);
}
return columns;
}
const renderGame = () => {
const lines = [];
for (let i = 0; i < gameHeight; i++) {
lines.push(
<div id={i.toString()} className={styles.line}>
{renderLine(data[i] || [-1, -1])}
</div>
)
}
return lines;
}
return (
<>
<div className={styles.gameContainer}>
{renderGame()}
</div>
</>
)
解决方案
您在_data
这里直接修改,我假设它也是您从 Redux 存储中检索到的对象。这意味着您要在 reducer 之外修改 redux 存储。
这样的事情会引起各种副作用。
您不仅在这样做,而且还在修改lastIndexData
——这也是对 store 中对象的引用——在这里,你再次直接修改 store,而不是使用 reducer 更新它。
尝试
const moveStackLine = useCallback((data: GameData, directionCopy: 'left' | 'right') => {
// .concat will create a new array reference that you can (flatly) modify as you want
const _data = data.concat()
// .concat will create a new array reference that you can (flatly) modify as you want
lastIndexData = _data[_data.length - 1].concat();
推荐阅读
- java - 类中的 Java 方法不能应用于没有参数的给定类型
- python-3.x - 如何允许正则表达式搜索 '\xcf\x83' 这种字符串
- powershell - Jupyterlab 终端不工作,但 windows 中的 cmd 工作正常
- python - Flask - 通过 GET 请求发送数据
- terminal - 关闭 Zsh shell(或终端)时是否可以调用脚本?
- neo4j - 创建子节点之间的关系
- javascript - 显示 Bootstrap 4 模式,但在按钮内保持 href 工作
- go - 找不到包“rsc.io/quote”
- vue.js - Vuetify - 如何有条件地更改 v-btn 的点击处理程序和文本?
- pyspark - Pyspark:转换/转换为数字类型