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> </> ); }
问题原因
- 逻辑错误:两个连续的
if语句导致whatToShowInGrid.current永远无法切换到1。当current为0时,第一个if把它改成1,紧接着第二个if判断current为1,又把它改回0,等于没有任何变化。 - Ref的误用:React不会追踪
useRef的变化,虽然你通过setRerender触发了重渲染,但ref的修改不属于React的状态更新流程,不过这里的核心问题是逻辑错误导致状态根本没切换。 - 冗余的重渲染触发:完全不需要额外的
rerenderstate,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
相关产品推荐
相关产品推荐

