如何在LocalStorage中保存API渲染的动态折叠面板状态?
如何将动态折叠状态保存到LocalStorage并在刷新后恢复
你现在的代码只把选中的item存在了LocalStorage里,但没保存每个面板的折叠状态。我们可以调整状态管理方式,让折叠状态更容易存储和恢复,具体步骤如下:
1. 重构状态结构,统一管理折叠状态
原来你用item.id + 'Open'作为每个状态的键,分散的状态不好统一存到LocalStorage。我们改成一个对象expandedItems,键是item的id,值是对应的折叠状态(true=展开,false=收起)。
在组件初始化时,先从LocalStorage读取之前保存的状态,没有的话初始化为空对象:
constructor(props) { super(props); // 从LocalStorage读取保存的折叠状态,无数据则初始化为空对象 const savedExpanded = localStorage.getItem('expandedItems'); this.state = { ordersWaiting: [], // 保留你原有的其他状态 expandedItems: savedExpanded ? JSON.parse(savedExpanded) : {} }; }
2. 更新点击事件,同步保存折叠状态到LocalStorage
修改handleClick函数,更新expandedItems对象的同时,把它存入LocalStorage:
handleClick = (e, item) => { // 计算新的折叠状态:翻转当前item的状态,保留其他item的状态 const newExpanded = { ...this.state.expandedItems, [item.id]: !this.state.expandedItems[item.id] }; this.setState({ expandedItems: newExpanded }); // 将更新后的折叠状态持久化到LocalStorage localStorage.setItem('expandedItems', JSON.stringify(newExpanded)); // 保留你原有的业务逻辑 localStorage.setItem('currentopentab', JSON.stringify(item)); currentUserSubject.next(item); };
3. 修改渲染逻辑,适配新的状态结构
把原来判断折叠状态的地方改成用this.state.expandedItems[item.id],同时调整Collapse组件的in属性:
<List component="nav" subheader={<ListSubheader component="div">Waiting for order</ListSubheader>} className={classes.root} > { this.state.ordersWaiting.map((item, index) =>{ // 默认状态为收起(false) const isExpanded = this.state.expandedItems[item.id] || false; return ( <div key={item.id}> {/* 建议用item.id作为key,比index更可靠 */} <ListItem button className={classes.orderheader} > <div className={classes.expandContainer} onClick={((e) => this.handleClick(e, item))}> <ListItemIcon> <InboxIcon /> </ListItemIcon> <ListItemText inset primary={item.userName} secondary={item.timeStamp}/> {isExpanded ? <ExpandLess /> : <ExpandMore />} </div> <Fab color="secondary" aria-label="Add" className={classes.fabButton}> <AddIcon onClick={((e) => this.prepareOrder(e, item))} /> </Fab> </ListItem> <Collapse in={isExpanded} timeout="auto" unmountOnExit> <List component="div" disablePadding> { item.order.map((products, index) =>{ return (<ListItem key={index} button className={classes.nested}> <ListItemIcon> <StarBorder /> </ListItemIcon> <ListItemText inset primary={products.qty + ' x ' + products.product} /> </ListItem> ) } )} </List> </Collapse> </div> ) })} </List>
额外小优化
- 将列表项的
key从index改为item.id:当列表项顺序变化时,React能更准确地识别每个元素,避免不必要的重渲染。 - 如果需要实现单选折叠(同一时间只能展开一个面板),可以在
handleClick里先把所有item的状态设为false,再将当前item设为翻转后的状态,再存入LocalStorage。
这样修改后,每次用户点击折叠面板时,状态都会被保存到LocalStorage,页面刷新后会自动读取并恢复之前的折叠状态啦!
内容的提问来源于stack exchange,提问作者Salman
相关产品推荐
相关产品推荐

