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

为什么修改useState中存储的数组时会同步改动原始数组?

问题根因

  • 你使用的[...genreOptions]是浅拷贝,仅复制了外层数组的引用,内部存储的每一个[流派名, 布尔值]子数组仍然和原始genreOptions共享引用,修改子数组的值会同步影响原始数组。
  • 代码中g[(i, 1)]的写法存在语法误区:逗号表达式会返回最后一个值,这里等价于g[1],虽然当前场景下结果符合预期,但属于错误写法,建议直接写g[1]。
  • 你直接修改了状态引用指向的子数组内容(g[1] = !g[1]),属于直接变更React状态,不符合React不可变更新的规范。
  • 全局声明的genreOptClone只会初始化一次,在组件运行过程中已经被修改,无法作为初始值的备份使用。

修复方案

  1. 初始化状态时直接从原始数组做双层拷贝,保证和原始数组完全隔离
  2. 点击事件触发时,按照不可变更新的规则生成新的数组,不修改原有引用
  3. 修正语法错误,删除不必要的逗号表达式

修复后代码

const genreOptions = [
  ["rock", true],
  ["pop", true],
  ["punk", true],
  ["acoustic", true],
  ["alternative", true],
  ["ambient", true],
  ["blues", true],
  ["classical", true],
  ["chill", true],
  ["comedy", true],
  ["country", true],
  ["dance", true],
  ["disco", true],
  ["electronic", true],
  ["folk", true],
  ["drum and bass", true],
  ["dub", true],
  ["funk", true],
  ["gospel", true],
  ["garage", true],
  ["hip hop", true],
  ["house", true],
  ["indie", true],
  ["jazz", true],
  ["metal", true],
  ["new age", true],
  ["opera", true],
  ["r&b", true],
  ["reggae", true],
  ["rock and roll", true],
  ["ska", true],
  ["soul", true],
  ["soundtracks", true],
  ["techno", true],
  ["world music", true],
];

function ShuffleControls({ nextTrack, currentTrack, token: receivedToken }) {
  // 初始化时直接从原始数组做双层拷贝,完全隔离引用
  const [genres, setGenres] = useState(() => 
    genreOptions.map(item => [...item]).sort()
  );

  const handleGenreClick = (i) => {
    // 不可变更新:生成全新的数组,不修改原有状态引用
    setGenres(prev => {
      const newGenres = [...prev];
      newGenres[i] = [...newGenres[i]];
      newGenres[i][1] = !newGenres[i][1];
      return newGenres;
    });
  };

  return (
    <div>
       {genres.map((g, i) => (
            <button
              type="button"
              key={i}
              onClick={() => {
                handleGenreClick(i);
                console.log("genreOptions onClick: ", genreOptions);
              }}
              className={g[1] ? "genres-btn" : "genres-btn btn-disabled"}
            >
              {g[0]}
            </button>
          ))}
   </div>
  );
}

export default ShuffleControls;

额外说明

如果需要重置状态,直接调用setGenres(genreOptions.map(item => [...item]).sort())即可,不会影响原始genreOptions的值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:54:04