为什么react-bootstrap未激活Tab内的useEffect会在组件渲染前触发?
问题原因
react-bootstrap 的 Tabs 组件默认会一次性渲染所有 Tab 下的子组件,仅通过 CSS 隐藏非激活标签的内容,并不是未渲染。所以 Positions 组件会在 Tabs 初始化时就完成挂载,空依赖的 useEffect 自然会提前执行,这和 Hooks 的工作原理无关,是组件库的默认渲染逻辑导致的。
mountOnEnter 不生效的原因
你在 Tabs 上配置了 transition={false} 关闭了过渡动画,而 mountOnEnter 依赖过渡动画的生命周期钩子才能触发,关闭过渡后这个属性自然不会生效。
解决方案
方案1:配合过渡动画使用 mountOnEnter
去掉 transition={false} 配置,给需要懒加载的 Tab 加上 mountOnEnter 属性即可,组件会在第一次切换到对应标签时才挂载,切换到其他标签时不会卸载,下次进入也不会重复触发初始化请求,完全符合你的需求:
const Panes = (props) => ( <Tabs className="pane" defaultActiveKey="construction"> <Tab eventKey="home" title="Home" mountOnEnter> <Home username={props.username} password={props.password} /> </Tab> <Tab eventKey="positions" title="Positions" mountOnEnter> <Positions /> </Tab> <Tab eventKey="trades" title="Trade History" mountOnEnter> <Trades /> </Tab> <Tab eventKey="construction" title="Portfolio Construction"> <Construction username={props.username} /> </Tab> <Tab eventKey="risk" title="Risk Analytics" mountOnEnter> <Risk /> </Tab> </Tabs> )
如果不需要默认的过渡效果,也可以自定义一个无动画的过渡组件传入,不影响 mountOnEnter 的逻辑。
方案2:受控模式手动控制渲染
如果不想改过渡配置,可以把 Tabs 改成受控组件,自己持有当前激活的标签key,仅匹配时才渲染对应子组件:
import { useState } from 'react' const Panes = (props) => { const [activeKey, setActiveKey] = useState('construction') return ( <Tabs className="pane" activeKey={activeKey} onSelect={(key) => setActiveKey(key)} transition={false} > <Tab eventKey="home" title="Home"> {activeKey === 'home' && <Home username={props.username} password={props.password} />} </Tab> <Tab eventKey="positions" title="Positions"> {activeKey === 'positions' && <Positions />} </Tab> <Tab eventKey="trades" title="Trade History"> {activeKey === 'trades' && <Trades />} </Tab> <Tab eventKey="construction" title="Portfolio Construction"> <Construction username={props.username} /> </Tab> <Tab eventKey="risk" title="Risk Analytics"> {activeKey === 'risk' && <Risk />} </Tab> </Tabs> ) }
如果需要切走标签就卸载组件,再给 Tab 加上 unmountOnExit 属性即可,适合每次进入标签都需要刷新数据的场景。
内容的提问来源于stack exchange,提问作者Dallin Davis
相关产品推荐
相关产品推荐

