如何解决在reactjs中,是否可以创建一个不重置内容状态的选项卡控件?
这是我的react hooks代码:
function Panel({children,title}){
var [count,set_count]=React.useState(0)
React.useEffect(_=>{
console.log(title,'mount')
return _x=>console.log(title,'unmount')
})
function onClick(){
set_count(count+10)
}
return <>{count}<button {...{onClick}}>up</button><div>{children}</div></>
}
function Tabs({children}){
var [selected,set_selected]=React.useState(children[0].key)
var tabs= children.map(x=>{
function onClick(){
set_selected(x.key)
}
var className=(selected==x.key)?'tab selected':'tab'
return <div {...{className,onClick,key:x.key}}>{x.props.title||x.key}</div>
})
var panel=children.find(x=>x.key==selected)
return <><div>{tabs}</div>{panel}</>
}
function TabsPage(){
return <Tabs>
<Panel key='the_tab1' title='The tab1 title'> tab1<b>rrr</b></Panel>
<Panel key='the_tab2' title='The tab2 title'> tab2</Panel>
</Tabs>
}
目标是使用react钩子创建具有任意内容的简单选项卡控件(称为面板)。该代码有效,除了每次用户更改活动选项卡时都可以安装/卸载面板组件。结果面板状态重置。
我的问题:更改标签时如何使状态不重置?不使用redux之类的全局状态存储,有可能吗?
解决方法
选项卡更改时状态会重置,因为每次更改选定的选项卡时,都会在“选项卡”组件中重新渲染面板变量。要保持状态,您有2个选项:
- 将状态保留在TabsPage组件中,而不是redux,因此在卸载面板时不会丢失状态。
- 始终显示所有选项卡,但仅显示选定的选项卡(使用显示或可见性之类的CSS属性)。这样,将不会卸载组件,因此您可以保持状态。
此外,即使与您的问题无关,我也要注意,在Panel组件中使用的useEffect
代码不会跟踪安装/卸载状态。而是在每次渲染时触发它。如果您希望在安装和卸载时调用一次效果,则需要向效果添加一个依赖项数组。选中React documentation。
这是一个相当误解,认为react钩子中的useEffect
具有安装效果,而useEffect
中的清理具有卸载效果(即使我在学习钩子时也曾想过)。
useEffect
发生的时间。当前,您拥有的useEffect
在每个渲染上都执行,因为它没有依赖性。
我强烈建议您阅读此博客post,以了解useEffect
的行为。
解决此问题的方法是实现活动面板TabsPage
并将selectedKey发送到Panel
。如果键相同,则可以切换显示内容。
因此该组件看起来与此类似
function TabsPage() {
const [selectedKey,setSelectedKey] = React.useState(the_tab1);
const handlePanelClick = useCallback((id) => {
setSelectedKey(id);
},[]);
return (
<Tabs>
<Panel
key="the_tab1"
title="The tab1 title"
selectedKey={selectedKey}
onClick={handlePanelClick}
>
tab1<b>rrr</b>
</Panel>
<Panel
key="the_tab2"
title="The tab2 title"
selectedKey={selectedKey}
onClick={handlePanelClick}
>
tab2
</Panel>
</Tabs>
);
}
function Panel({ key,children,handlePanelClick,selectedKey }) {
return (
<>
{/** to show hide the panel */}
<button onClick={() => handlePanelClick(key)}>+</button>
{key === selectedKey && <div>{children}</div>}
</>
);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。