You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React StrictMode下组件重复渲染致角色移动翻倍问题求助

问题原因与解决方案

问题根源

你遇到的问题核心不是StrictMode本身,而是状态更新函数违反了React的不可变原则,加上StrictMode的开发模式检测放大了这个问题:

  • 在updatePlayerPos中,你用了prev.pos.x += x这种写法,直接修改了React的前状态对象(prev),属于不纯操作。
  • StrictMode在开发环境下会两次执行状态更新的回调函数,目的是检测这类不纯的副作用。第一次执行时已经修改了prev对象的属性,第二次执行时用的是已经被修改过的prev,所以导致位置变化翻倍。

解决方案

修复的关键是保证状态更新函数是纯函数,绝对不要直接修改prev状态,而是创建新的对象来保存新状态:

修改usePlayer中的updatePlayerPos函数:

import { useState } from 'react';

export const usePlayer = () => {
  const [player, setPlayer] = useState({
    pos: { x: 0, y: 0 },
  });

  const updatePlayerPos = ({ x, y }) => {
    console.log('updatePlayerPos');
    setPlayer((prev) => ({
      ...prev,
      // 不要修改prev.pos,而是计算新的x/y值,创建新的pos对象
      pos: { 
        x: prev.pos.x + x, 
        y: prev.pos.y + y 
      },
    }));
  };

  return [updatePlayerPos, player];
};

为什么这样有效

  • 这里不再直接修改prev.pos,而是基于prev.pos.x和传入的x计算出新的x值,创建一个全新的pos对象,保证了状态的不可变性。
  • 即使StrictMode两次执行这个更新函数,每次拿到的prev都是原始的未修改状态,两次执行的结果都是相同的,React会自动忽略第二次重复的更新。

额外注意

  • React的状态必须是不可变的,直接修改状态对象不仅会导致StrictMode下的问题,还可能引发组件不重新渲染、状态不一致等难以排查的bug。
  • StrictMode是开发环境的工具,帮你提前发现这类问题,上线生产环境后不会有双重执行的情况,但遵循不可变原则是React开发的基础规范。

内容的提问来源于stack exchange,提问作者Zim92

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:35:16