Next.js中React-Bootstrap Accordion状态持久化到localStorage失败
问题解决:React-Bootstrap Accordion 状态持久化到 localStorage(Next.js)
问题分析
你当前代码的核心问题有两个:
- 使用了非受控属性
defaultActiveKey,它仅在组件初始化时生效,后续通过useState更新状态不会同步到Accordion组件。 - 未处理Next.js SSR环境下
localStorage不存在的情况,且初始状态未兼容localStorage为空的场景。
修正后的代码
import { useState, useEffect } from 'react' import Accordion from 'react-bootstrap/Accordion' export default function Example() { // 初始化状态:优先取localStorage的值,为空则设空数组,同时兼容SSR const [expandedItems, setExpandedItems] = useState([]) useEffect(() => { if (typeof window !== 'undefined') { const savedExpanded = localStorage.getItem('expandedItems') if (savedExpanded) { setExpandedItems(JSON.parse(savedExpanded)) } } }, []) const handleAccordionSelect = (selectedKey) => { let updatedExpanded if (selectedKey === null) { updatedExpanded = [] } else { // 处理alwaysOpen模式下的多选逻辑:切换选中状态 updatedExpanded = expandedItems.includes(selectedKey) ? expandedItems.filter(key => key !== selectedKey) : [...expandedItems, selectedKey] } setExpandedItems(updatedExpanded) localStorage.setItem('expandedItems', JSON.stringify(updatedExpanded)) } return ( <Accordion alwaysOpen activeKey={expandedItems} // 改用受控属性activeKey onSelect={handleAccordionSelect} > <Accordion.Item eventKey="0"> <Accordion.Header>Accordion Item #1</Accordion.Header> <Accordion.Body> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </Accordion.Body> </Accordion.Item> <Accordion.Item eventKey="1"> <Accordion.Header>Accordion Item #2</Accordion.Header> <Accordion.Body> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </Accordion.Body> </Accordion.Item> </Accordion> ); }
关键修改点
- 替换
defaultActiveKey为activeKey:将Accordion改为受控组件,确保状态变化时组件实时响应。 - 兼容Next.js SSR环境:在
useEffect中判断typeof window !== 'undefined',避免服务器端渲染时访问localStorage报错。 - 完善状态更新逻辑:在
handleAccordionSelect中正确处理alwaysOpen模式下的多选切换,确保点击已展开项时移除对应key,未展开时添加。 - 初始状态容错:当
localStorage中无保存数据时,初始化为空数组,避免null导致的异常。
内容的提问来源于stack exchange,提问作者Anik Sarker
相关产品推荐
相关产品推荐

