React中a.list=[]清空数组页面无更新但length=0生效原因问询
问题原因分析
核心根源
问题出在子组件冗余state + 两种数组清空操作的引用差异两方面:
- 子组件
TaskCallFunc将父组件传入的taskData存在了自身的内部state中,且仅在组件首次渲染时赋值一次,后续父组件更新props时,子组件的内部state不会自动同步。 - 两种清空数组的写法本质是完全不同的操作:
a.list = []:是给新的acty对象的list属性赋值了一个全新的空数组,此时父组件state的list引用发生了变化,传给子组件的props也更新了,但子组件仍然使用自身state中存储的老数组引用,老数组的内容没有变化,所以页面不会清空。a.list.length = 0:是直接修改原有数组对象本身的内容,子组件state中存储的还是这个老数组的引用,读取时数组内容已经被清空,所以页面会同步更新。
另外你的代码还存在不符合React单向数据流规范的问题:子组件直接修改props传入的数组元素属性、父组件直接修改原state的值,这也是引发状态不同步的隐患。
解决方案
最优方案:删除子组件冗余state
子组件不需要独立维护state,直接使用父组件传入的props渲染即可,彻底避免props和state不同步的问题:
function TaskCallFunc({data, action}: ItaskCell) { const HandleSlecet = (x: number) => { // 不要直接修改props里的数据,建议通过回调通知父组件更新状态,遵守单向数据流 const newList = data.list.map(item => { if(item.id === x) return {...item, finish: !item.finish} return item }) // 父组件实现updateList方法,通过props传给子组件调用即可 // updateList(newList) action() } const handleMap = () => { return data.list.map((v, i) => { return <li key={v.id}> {v.id}: {v.content} <input type="checkbox" checked={v.finish} onChange={() => HandleSlecet(v.id)} /> </li> }); } return <ul>{handleMap()}</ul>; }
父组件状态修改优化
不要直接修改原state的值,始终生成新的状态对象/数组:
const handleAdd = () => { if (input_ref.current) { if (input_ref.current.value === '') { alert("输入内容 不能为空!"); return; } const newItem = { id: acty.list.length, content: content, finish: false } // 生成全新数组,不修改原state setActivity({ ...acty, list: [newItem, ...acty.list] }); input_ref.current.value = ""; } } const clearTask = () => { setActivity({ ...acty, list: [] }); }
内容的提问来源于stack exchange,提问作者tong tian
相关产品推荐
相关产品推荐

