React调用setState后状态未更新、组件未重渲染问题求助
问题根源
- 你没有正确使用React组件:
ChangeButton是组件,不能直接当成普通函数调用ChangeButton(_subl[0]),必须用<ChangeButton />的形式渲染,否则组件的状态无法被React保存,每次父组件渲染都会重置状态,看起来就像setState没生效。 - 组件参数获取错误:React组件的第一个参数永远是props对象,你现在写的
const ChangeButton = (_testSubL) =>拿到的其实是整个props对象,不是你传的数组,导致你后续的取值判断全错。 - 点击逻辑用了固定的props值而非当前状态:你传入组件的props是初始固定值,不会随状态变化,点击时判断用
_testSubL而非自己维护的btUS,逻辑自然不符合预期。 - setState后立刻打印拿到旧值是正常现象:React的setState是异步批量更新的,要拿到更新后的状态需要在
useEffect监听btUS,或者在下次组件渲染时查看。
修正代码
import React, { useState, useEffect } from 'react' import { CButton, CCol, CRow, CContainer } from '@coreui/react' const inp1 = { id: 2, TestPhase: 'TestPhase', results: [ [['File Input', 'some Doc', 'file']], [['Some Stuff available', 'pass', 'cbutton']], [['Some other Stuff available', '', 'cbutton']], ], }.results // 组件参数改为取props里的testSubL const ChangeButton = ({ testSubL }) => { const [btUS, setbtUS] = useState(testSubL) useEffect(() => { console.log('useEffect 最新btUS: ', btUS) }, [btUS]) return ( <> {/* 这里加条件渲染示例,根据状态显示不同的按钮颜色 */} <CButton className="mx-1" color={btUS[1] === 'pass' ? 'success' : btUS[1] === 'fail' ? 'danger' : 'secondary'} shape="rounded" size="sm" onClick={() => { console.log('点击时当前btUS: ', btUS) // 所有判断用当前状态btUS,不要用props的testSubL if (btUS[2] === 'cbutton') { let newState if (btUS[1] === 'pass') { newState = [btUS[0], 'fail', btUS[2]] } else if (btUS[1] === 'fail') { newState = [btUS[0], 'pass', btUS[2]] } else if (btUS[1] === '') { newState = [btUS[0], 'pass', btUS[2]] } // 传入新的数组引用,确保React检测到状态变化 setbtUS([...newState]) } }} > {/* 按钮文本也根据状态变化,验证条件渲染生效 */} {btUS[1] || '未设置'} </CButton> </> ) } const TestMain = () => { return ( <> <CContainer> <h3>Just some Test Page</h3> {inp1.map((_subl) => ( <CRow className="justify-content-center pt-1" key={_subl[0][0]}> <CCol md="2">Some Icon: {_subl[0][1]}</CCol> <CCol md="3">{_subl[0][0]}</CCol> {/* 用组件形式渲染,通过props传值 */} <CCol md="3"><ChangeButton testSubL={_subl[0]} /></CCol> </CRow> ))} </CContainer> </> ) } export default TestMain
补充说明
如果后续需要把按钮状态同步到父组件,只需要在父组件定义对应状态,给ChangeButton传onChange回调,点击时把新值通过回调传给父组件即可。
内容的提问来源于stack exchange,提问作者ReinerMal
相关产品推荐
相关产品推荐

