删除数组内对象后React列表未重新渲染问题咨询
问题原因
- 核心错误:渲染列表时遍历的是组件外部的常量
firstItems,而你调用setItems更新的是存放在state中的响应式变量items。外部常量不会随着state变更而变化,所以页面不会触发对应重渲染。 - 额外问题:删除列表项后没有同步清理
layout状态里对应id的布局配置,后续使用react-grid-layout可能会出现匹配异常。
修正方案
把渲染逻辑里的firstItems.map改成items.map,同时在删除逻辑里同步更新layout状态,建议state更新用函数式写法避免闭包陷阱,修正后代码如下:
import Sample from './SampleBlock' import React from 'react' import { useState } from 'react' import { Responsive, WidthProvider } from 'react-grid-layout' const ResponsiveGridLayout = WidthProvider(Responsive) const firstItems = [ { i: '1', comp: Sample }, { i: '2', comp: Sample }, { i: '3', comp: Sample }, { i: '4', comp: Sample }, { i: '5', comp: Sample }, ] const firstLayout = { lg: [ { i: '1', x: 0, y: 0, w: 1, h: 2 }, { i: '2', x: 1, y: 0, w: 3, h: 2 }, { i: '3', x: 4, y: 0, w: 1, h: 2 }, { i: '4', x: 0, y: 2, w: 2, h: 2 }, { i: '5', x: 0, y: 2, w: 6, h: 2 }, ], } export default function Content() { const [layout, setLayout] = useState(firstLayout) const [items, setItems] = useState(firstItems) const edit = (_, allLayouts) => { console.log(allLayouts) setLayout(allLayouts) } const onRemoveItem = (itemId) => { // 同步更新items和layout setItems(prev => prev.filter((item) => item.i !== itemId)) setLayout(prev => { return { ...prev, lg: prev.lg.filter(item => item.i !== itemId) // 如果要兼容md/sm等其他断点,在这里同步处理对应断点的布局数组即可 } }) } return ( <ResponsiveGridLayout className='layout' layouts={layout} onRemoveItem={onRemoveItem} onLayoutChange={edit} breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 1 }} rowHeight={60}> {/* 遍历state中的响应式items */} {items.map((item) => ( <div key={item.i} className='widget' data-grid={{ w: 3, h: 2, x: 0, y: Infinity }}> <button onClick={() => {onRemoveItem(item.i)}}>{item.i}</button> <div style={{ width: '100%', height: '100%', backgroundColor: '#ccc' }}> {React.createElement(item.comp, { key: item.i })}</div> </div> ))} </ResponsiveGridLayout> ) }
内容的提问来源于stack exchange,提问作者Enes
相关产品推荐
相关产品推荐

