React组件调用setState后未重新渲染,控制台日志正常,原因何在?
问题描述
以下是React组件代码:
import React, {forwardRef, useState, useEffect} from 'react' import type {SxProp} from '@primer/react' import {UnderlinePanels} from '@primer/react/experimental' export type TabsProps = SxProp & {} export interface TabsHandle {} const Tabs = forwardRef<TabsHandle, TabsProps>(({}, _ref) => { const [tab, setTab] = useState<1 | 2>(1) useEffect(() => { console.log('Tab', tab) }, [tab]) return ( <UnderlinePanels> <UnderlinePanels.Tab aria-selected={tab === 1}>Tab 1</UnderlinePanels.Tab> <UnderlinePanels.Panel> Panel 1<button onClick={() => setTab(2)}>Switch</button> </UnderlinePanels.Panel> <UnderlinePanels.Tab aria-selected={tab === 2}>Tab 2</UnderlinePanels.Tab> <UnderlinePanels.Panel>Panel 2 </UnderlinePanels.Panel> </UnderlinePanels> ) })
点击按钮后,控制台会打印“2”,但组件并未切换到Tab 2,仍显示Tab 1,请问这是什么原因?
原因及解决方案
UnderlinePanels组件状态逻辑冲突:Primer的UnderlinePanels是封装好的组件,自身会维护选中标签页的内部状态。你手动给Tab设置aria-selected属性,会和组件内部的状态控制逻辑冲突,导致UI无法正确更新。虽然你的tab状态已经改变并触发了useEffect打印,但组件自身不认可外部手动设置的选中状态,所以不会切换显示对应的面板。- 未遵循组件使用规范:
UnderlinePanels需要通过selectedIndex属性控制选中项,同时通过onChange回调接收状态变化。正确的做法是将外部状态与组件的selectedIndex绑定,而非直接操作Tab的aria-selected属性。
修正后的代码示例:
import React, {forwardRef, useState} from 'react' import type {SxProp} from '@primer/react' import {UnderlinePanels} from '@primer/react/experimental' export type TabsProps = SxProp & {} export interface TabsHandle {} const Tabs = forwardRef<TabsHandle, TabsProps>(({}, _ref) => { const [selectedIndex, setSelectedIndex] = useState(0) return ( <UnderlinePanels selectedIndex={selectedIndex} onChange={setSelectedIndex}> <UnderlinePanels.Tab>Tab 1</UnderlinePanels.Tab> <UnderlinePanels.Panel> Panel 1<button onClick={() => setSelectedIndex(1)}>Switch</button> </UnderlinePanels.Panel> <UnderlinePanels.Tab>Tab 2</UnderlinePanels.Tab> <UnderlinePanels.Panel>Panel 2 </UnderlinePanels.Panel> </UnderlinePanels> ) })
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

