React Native二维数组点击修改时多行同列值同步变更问题
问题分析与解决方案
问题核心原因
- 二维数组引用共享:初始创建数组时,
Array(numberOfRows).fill(Array(numberOfCols).fill(false))会把同一个子数组引用填充到每一行,所有行共享同一个数组实例,修改任意一行的列值都会同步影响所有行。 - 状态更新浅拷贝失效:
const rowsData = [...rows]仅浅拷贝了外层数组,内层子数组还是原引用,修改rowsData[rowIdx][colIdx]依然会改动原状态里的所有行。 - 不稳定的组件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
相关产品推荐
相关产品推荐

