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

React删除数组及localStorage列表项后视图未实时更新问题

问题根源
  • 子组件中通过const [deleted, setDelted] = useState(store)将父组件传入的列表数据拷贝为本地状态,这个初始化操作仅在子组件首次挂载时执行一次,后续父组件传入的store更新时,本地的deleted不会自动同步。
  • 点击Yes按钮时,所有修改操作都只作用在子组件本地的deleted状态上,没有将删除后的结果同步回父组件。父组件用来渲染实际列表的源store没有发生变化,自然不会触发视图重渲染,只有其他操作触发父组件重渲染时,才会感知到数据变动。
  • 子组件额外维护了no状态控制遮罩显隐,和父组件通过props.setDel控制的遮罩状态重复,很容易出现状态不同步的问题。
修复方法

遵循React单向数据流原则:哪个组件维护数据,就由哪个组件负责修改数据,子组件不存冗余的同源状态,仅通过父组件传入的回调触发数据修改。

  1. 先在父组件中实现删除逻辑,将删除方法通过props传给子组件:
// 父组件代码示例
import { useState, useCallback } from 'react';
import Delete from './Delete';

function Parent() {
  const [store, setStore] = useState(() => {
    // 初始化时从localStorage读取数据
    return Object.keys(localStorage)
      .filter(key => key.startsWith('task_')) // 按自身存储key规则过滤即可
      .map(id => JSON.parse(localStorage.getItem(id)));
  });
  const [delVisible, setDelVisible] = useState(false);
  const [currentDelId, setCurrentDelId] = useState(null);

  // 定义删除逻辑,维护源store
  const handleDelete = useCallback((id) => {
    const updatedStore = store.filter(task => task.id !== id);
    setStore(updatedStore);
    localStorage.removeItem(id);
  }, [store]);

  return (
    <div>
      {/* 列表渲染逻辑 */}
      {store.map(task => (
        <div key={task.id}>
          <span>{task.content}</span>
          <button onClick={() => {
            setCurrentDelId(task.id);
            setDelVisible(true);
          }}>删除</button>
        </div>
      ))}
      {/* 给删除组件传入所需props */}
      {delVisible && (
        <Delete 
          id={currentDelId}
          setDel={setDelVisible}
          onDelete={handleDelete}
        />
      )}
    </div>
  )
}

export default Parent;
  1. 简化子组件代码,删除冗余的本地状态,直接调用父组件传入的方法完成操作:
import React from "react";
import styles from "./Delete.module.css";

function Delete(props) {
  const noBtnHandler = () => {
    props.setDel(false);
  };

  const yesBtnHandler = () => {
    props.onDelete(props.id);
    props.setDel(false);
  };

  return (
    <div className={styles.delOn}>
      <section>
        <div>
          <h3>Are you Sure ?</h3>
        </div>
        <div>
          <button type="button" onClick={yesBtnHandler}>
            Yes
          </button>
          <button type="button" onClick={noBtnHandler}>
            No
          </button>
        </div>
      </section>
    </div>
  );
}

export default Delete;
注意事项
  • 不要在子组件中拷贝父组件传入的、用于页面渲染的源数据到本地state,否则极易出现数据不同步的问题。
  • 同一份状态只需要在最上层用到它的组件中维护一次,下层组件通过props获取状态、通过回调触发修改即可,不要重复维护多份状态。
  • 修改状态后视图不更新时,优先检查是不是修改了非state的副本,或者修改的状态和渲染用的状态不是同一份。

内容的提问来源于stack exchange,提问作者Abhishek Lingwal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 09:46:02