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

React函数式组件修改布尔state后未重渲染,方块切换失效?

React网格方块切换失效问题修复

问题描述

我写了一个简单的React函数式组件,渲染一个2行2列的grid容器和一个按钮。准备了两组JSX数组:一组是红色背景的div,用来填充网格;另一组是黄色背景的div,想点击按钮时替换网格里的红色方块。我通过修改布尔类型的state来强制组件重渲染,但点击按钮后网格还是显示红色方块,切换功能没生效。

原代码如下:

import { useState, useRef } from "react";
import React from 'react';
import './styles.css';

export default function MyComponent() {
  // 用来触发重渲染的state
  const [rerender, setRerender] = useState(false)
  // 用来控制显示哪组方块的ref
  const whatToShowInGrid = useRef(0)

  let myArray = [1,2,3,4]

  // 红色方块数组
  let displaySquares  = myArray.map(member=> <div className="divRedBackground" key={member} ></div>)
  // 黄色方块数组
  let displaySquares1 = myArray.map(member=> <div className="divYellowBackground" key={member} ></div>)

  // 按钮点击事件处理函数
  function changeSquaresInGrid(){
    console.log(`You clicked the button!`)

    // 尝试切换whatToShowInGrid.current的值
    if (whatToShowInGrid.current === 0) {
      whatToShowInGrid.current = 1
    }

    if (whatToShowInGrid.current === 1) {
      whatToShowInGrid.current = 0
    }

    // 强制重渲染
    setRerender(!rerender)
  }

  return (
    <>
      {/*网格容器*/}
      <div className='gridContainer'>
        { whatToShowInGrid.current === 0 ? <> {displaySquares} </> : <> {displaySquares1} </> }   
      </div>

      {/*切换按钮*/}
      <div className="button1" onClick={changeSquaresInGrid}>
        <p className="button1Text">Click me</p>
      </div>
    </>
  );
}

问题原因

  1. 逻辑错误:两个连续的if语句导致whatToShowInGrid.current永远无法切换到1。当current为0时,第一个if把它改成1,紧接着第二个if判断current为1,又把它改回0,等于没有任何变化。
  2. Ref的误用:React不会追踪useRef的变化,虽然你通过setRerender触发了重渲染,但ref的修改不属于React的状态更新流程,不过这里的核心问题是逻辑错误导致状态根本没切换。
  3. 冗余的重渲染触发:完全不需要额外的rerender state,React中修改state本身就会自动触发组件重渲染。

修复方案

方案1:用State替代Ref(推荐)

把控制显示状态的变量改成React State,这是React中管理组件状态的标准方式,不需要手动触发重渲染。

import { useState } from "react";
import './styles.css';

export default function MyComponent() {
  // 用state存储显示状态,初始值0对应红色方块
  const [displayMode, setDisplayMode] = useState(0)

  const myArray = [1,2,3,4]

  const redSquares = myArray.map(member => (
    <div className="divRedBackground" key={member}></div>
  ))
  const yellowSquares = myArray.map(member => (
    <div className="divYellowBackground" key={member}></div>
  ))

  const toggleSquares = () => {
    console.log('切换方块颜色')
    // 切换状态:0和1互转
    setDisplayMode(prevMode => prevMode === 0 ? 1 : 0)
  }

  return (
    <>
      <div className='gridContainer'>
        {displayMode === 0 ? redSquares : yellowSquares}
      </div>

      <div className="button1" onClick={toggleSquares}>
        <p className="button1Text">Click me</p>
      </div>
    </>
  );
}

方案2:修正Ref逻辑(不推荐)

如果一定要用Ref,先修正切换逻辑的bug,避免重复赋值:

import { useState, useRef } from "react";
import './styles.css';

export default function MyComponent() {
  const [rerender, setRerender] = useState(false)
  const displayMode = useRef(0)

  const myArray = [1,2,3,4]
  const redSquares = myArray.map(member => (
    <div className="divRedBackground" key={member}></div>
  ))
  const yellowSquares = myArray.map(member => (
    <div className="divYellowBackground" key={member}></div>
  ))

  const toggleSquares = () => {
    console.log('切换方块颜色')
    // 用else if避免重复赋值
    if (displayMode.current === 0) {
      displayMode.current = 1
    } else if (displayMode.current === 1) {
      displayMode.current = 0
    }
    setRerender(!rerender)
  }

  return (
    <>
      <div className='gridContainer'>
        {displayMode.current === 0 ? redSquares : yellowSquares}
      </div>

      <div className="button1" onClick={toggleSquares}>
        <p className="button1Text">Click me</p>
      </div>
    </>
  );
}

关键提示

  • 永远优先用useState管理组件的渲染状态,useRef仅用于处理DOM引用或不需要触发重渲染的可变值。
  • 避免手动触发重渲染,React会自动在state变化时更新组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:32:01