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

React中更新二维数组matrix状态后useEffect未重执行的问题

问题:修改React二维数组状态后组件未触发更新

我通过useState初始化了二维数组状态matrix,并编写了修改该数组的置零算法。控制台打印显示matrix内容已经变化,但依赖matrix的useEffect并未触发组件更新,只有在VS Code中输入内容时才会触发重渲染。尝试调整setMatrix的使用方式,问题仍未解决。

原代码

import React, {MouseEvent, useEffect, useState} from 'react'

const TwoDArray = () => {
 let twodarray:number[][] =  [
    [1,1,1,1],
    [1,0,1,1],
    [1,1,0,1],
    [0,0,0,1]
    ] 
  const [matrix, setMatrix] = useState(twodarray)
  
  const setMatrixZeros = (matrix: number[][], ) => { 
    let col0: number = 1, rows: number = matrix.length, cols = matrix[0].length
    
    for (let i: number = 0; i < rows; i++) {
      if (matrix[i][0] == 0) col0 = 0
      for (let j: number = 1; j < cols; j++) 
        if(matrix[i][j]==0) matrix[i][0] = matrix[0][j] = 0
    }
    
    for (let i: number = rows - 1; i >= 0; i--) { 
      for (let j: number = cols - 1; j >= 1; j--) {
        if (matrix[i][0] == 0 || matrix[0][j] == 0) matrix[i][j] = 0
      }
      if(col0==0) matrix[i][0] = 0 
    }
  }

  const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
    setMatrixZeros(matrix)
      
  }  
   
  useEffect(() => {
  }, [matrix]); // Only re-run the effect if matrix changes
  
console.log(matrix)
  return (
    <div className="twodarray">
      <div className="matrix">
        {    matrix.map((item, index) => { 
          return <div key={index} className='box-container'>
            {item.map((i, idx) =>
              <input type='text' key={idx} className='box' value={ i} readOnly/>)}</div>
    })}
      </div>
      <button onClick={handleClick }>Set Matrix Zeroes</button>
    </div>
  ) 
}

export default TwoDArray

问题原因

React的状态更新依赖引用变化判断状态是否改变。你在setMatrixZeros函数中直接修改了matrix的原数组(数组是引用类型),虽然数组内容变了,但数组的引用地址没有改变,React会认为状态没有更新,因此不会触发组件重渲染,useEffect也不会执行。

解决方法

必须创建原数组的副本,在副本上修改内容,再通过setMatrix传入新的数组副本,触发状态更新。

修改后的代码示例

import React, {MouseEvent, useEffect, useState} from 'react'

const TwoDArray = () => {
 let twodarray:number[][] =  [
    [1,1,1,1],
    [1,0,1,1],
    [1,1,0,1],
    [0,0,0,1]
    ] 
  const [matrix, setMatrix] = useState(twodarray)
  
  // 修改函数,返回新的数组
  const setMatrixZeros = (originalMatrix: number[][]): number[][] => {
    // 深拷贝原数组,避免修改原状态
    const matrix = structuredClone(originalMatrix);
    let col0: number = 1, rows: number = matrix.length, cols = matrix[0].length
    
    for (let i: number = 0; i < rows; i++) {
      if (matrix[i][0] == 0) col0 = 0
      for (let j: number = 1; j < cols; j++) 
        if(matrix[i][j]==0) matrix[i][0] = matrix[0][j] = 0
    }
    
    for (let i: number = rows - 1; i >= 0; i--) { 
      for (let j: number = cols - 1; j >= 1; j--) {
        if (matrix[i][0] == 0 || matrix[0][j] == 0) matrix[i][j] = 0
      }
      if(col0==0) matrix[i][0] = 0 
    }
    return matrix;
  }

  const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
    // 生成新数组并设置状态
    const newMatrix = setMatrixZeros(matrix);
    setMatrix(newMatrix);
  }  
   
  useEffect(() => {
    console.log('matrix更新,触发useEffect');
  }, [matrix]); 

  console.log(matrix)
  return (
    <div className="twodarray">
      <div className="matrix">
        {    matrix.map((item, index) => { 
          return <div key={index} className='box-container'>
            {item.map((i, idx) =>
              <input type='text' key={idx} className='box' value={ i} readOnly/>)}</div>
    })}
      </div>
      <button onClick={handleClick }>Set Matrix Zeroes</button>
    </div>
  ) 
}

export default TwoDArray

关键修改点

  1. 使用structuredClone深拷贝原数组,确保不直接修改原状态。
  2. 修改setMatrixZeros函数,让它返回处理后的新数组。
  3. 在handleClick中调用函数得到新数组,再通过setMatrix更新状态,此时状态引用改变,React会触发组件重渲染和useEffect执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:35:19