You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
    );
}

关键修改点

  1. 替换defaultActiveKey为activeKey:将Accordion改为受控组件,确保状态变化时组件实时响应。
  2. 兼容Next.js SSR环境:在useEffect中判断typeof window !== 'undefined',避免服务器端渲染时访问localStorage报错。
  3. 完善状态更新逻辑:在handleAccordionSelect中正确处理alwaysOpen模式下的多选切换,确保点击已展开项时移除对应key,未展开时添加。
  4. 初始状态容错:当localStorage中无保存数据时,初始化为空数组,避免null导致的异常。

内容的提问来源于stack exchange,提问作者Anik Sarker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 22:18:29