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

React Native二维数组点击修改时多行同列值同步变更问题

问题分析与解决方案

问题核心原因

  1. 二维数组引用共享:初始创建数组时,Array(numberOfRows).fill(Array(numberOfCols).fill(false))会把同一个子数组引用填充到每一行,所有行共享同一个数组实例,修改任意一行的列值都会同步影响所有行。
  2. 状态更新浅拷贝失效:const rowsData = [...rows]仅浅拷贝了外层数组,内层子数组还是原引用,修改rowsData[rowIdx][colIdx]依然会改动原状态里的所有行。
  3. 不稳定的组件Key:用Math.random()作为组件Key会导致组件每次渲染都生成新Key,引发不必要的重渲染,甚至导致状态异常。

修正方案

1. 正确初始化二维数组

生成独立的子数组,避免引用共享:

const [rows, setRows] = useState<boolean[][]>(
  Array.from({ length: numberOfRows }, () => Array(numberOfCols).fill(false))
);

或用map实现:

const [rows, setRows] = useState<boolean[][]>(
  Array(numberOfRows).map(() => Array(numberOfCols).fill(false))
);

2. 正确更新状态

更新时拷贝目标行,避免修改原引用:

const handleOnPress = (rowIdx: number, colIdx: number) => {
  setRows(prevRows => {
    const newRows = [...prevRows];
    // 单独拷贝要修改的行,切断原引用
    newRows[rowIdx] = [...newRows[rowIdx]];
    newRows[rowIdx][colIdx] = !newRows[rowIdx][colIdx];
    return newRows;
  });
};

3. 使用稳定的组件Key

用rowIdx和colIdx组合作为Key,保证稳定性:

<View key={rowIdx} ...>
  <TouchableOpacity key={`${rowIdx}-${colIdx}`} ...>

完整修正代码

export const GridComponent = ({
  numberOfRows,
  numberOfCols,
  dimens
}: Props) => {
  // 正确初始化二维数组,每行都是独立实例
  const [rows, setRows] = useState<boolean[][]>(
    Array.from({ length: numberOfRows }, () => Array(numberOfCols).fill(false))
  );

  const handleOnPress = (rowIdx: number, colIdx: number) => {
    setRows(prevRows => {
      const newRows = [...prevRows];
      newRows[rowIdx] = [...newRows[rowIdx]];
      newRows[rowIdx][colIdx] = !newRows[rowIdx][colIdx];
      return newRows;
    });
  };

  return (
    <View style={{ width: dimens.width, height: dimens.height }}>
      {rows.map((row, rowIdx) => (
        <View
          key={rowIdx}
          style={{ display: 'flex', flexDirection: 'row', marginBottom: 20 }}
        >
          {row.map((_col, colIdx) => (
            <TouchableOpacity
              key={`${rowIdx}-${colIdx}`}
              style={{
                backgroundColor: rows[rowIdx][colIdx] ? 'red' : '',
                borderWidth: 1,
                flex: dimens.width / numberOfCols,
                height: 50
              }}
              onPress={() => handleOnPress(rowIdx, colIdx)}
            >
              {colIdx}
            </TouchableOpacity>
          ))}
        </View>
      ))}
    </View>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 16:35:17