React文档-State数据扁平化

1、选择 State 结构

思考一下:

如果渲染列表, 并更新列表数据在下面展示~

state 过去常常是这样复制的:

  • items = [{ id: 0, title: 'pretzels'}, ...]
  • selectedItem = {id: 0, title: 'pretzels'}
    改了之后是这样的:
  • items = [{ id: 0, title: 'pretzels'}, ...]
  • selectedId = 0

重复的 state 没有了,你只保留了必要的 state!

现在,如果你编辑 selected 元素,下面的消息将立即更新。这是因为 setItems 会触发重新渲染,而 items.find(...) 会找到带有更新文本的元素。你不需要在 state 中保存 选定的元素,因为只有 选定的 ID 是必要的。其余的可以在渲染期间计算。

2、state "扁平化"(也称"规范化")嵌套更加容易

1、如果 state 嵌套太深,难以轻松更新,可以考虑将其"扁平化"。 这里有一个方法可以重构上面这个数据。不同于树状结构,每个节点的 place 都是一个包含 其子节点 的数组,你可以让每个节点的 place 作为数组保存 其子节点的 ID。然后存储一个节点 ID 与相应节点的映射关系。

2、现在要删除一个地点,您只需要更新两个 state 级别:

  • 其 父级 地点的更新版本应该从其 childIds 数组中排除已删除的 ID。
  • 其根级"表"对象的更新版本应包括父级地点的更新版本。
    places.js 文件
js 复制代码
export const initialTravelPlan = {
  0: {
    id: 0,
    title: '(Root)',
    childIds: [1],
  },
  1: {
    id: 1,
    title: 'Earth',
    childIds: [2, 7]
  },
  2: {
    id: 2,
    title: 'Africa',
    childIds: [3, 4, 5, 6]
  }, 
  3: {
    id: 3,
    title: 'Botswana',
    childIds: []
  },
  4: {
    id: 4,
    title: 'Egypt',
    childIds: []
  },
  5: {
    id: 5,
    title: 'Kenya',
    childIds: []
  },
  6: {
    id: 6,
    title: 'Madagascar',
    childIds: []
  }, 
  7: {
    id: 7,
    title: 'Morocco',
    childIds: [8, 9]
  },
  8: {
    id: 8,
    title: 'Nigeria',
    childIds: [11]
  },
  9: {
    id: 9,
    title: 'South Africa',
    childIds: []
  },
  10: {
    id: 10,
    title: 'Americas',
    childIds: [11, 12],   
  },
  11: {
    id: 11,
    title: 'Argentina',
    childIds: []
  },
};
js 复制代码
import { useState } from 'react';
import { initialTravelPlan } from './places.js';

export default function TravelPlan() {
  const [plan, setPlan] = useState(initialTravelPlan);

  function handleComplete(parentId, childId) {
    const parent = plan[parentId];
    // 创建一个其父级地点的新版本
    // 但不包括子级 ID。
    const nextParent = {
      ...parent,
      childIds: parent.childIds
        .filter(id => id !== childId)
    };
    // 更新根 state 对象...
    setPlan({
      ...plan,
      // ...以便它拥有更新的父级。
      [parentId]: nextParent
    });
  }

  const root = plan[0];
  const planetIds = root.childIds;
  return (
    <>
      <h2>Places to visit</h2>
      <ol>
        {planetIds.map(id => (
          <PlaceTree
            key={id}
            id={id}
            parentId={0}
            placesById={plan}
            onComplete={handleComplete}
          />
        ))}
      </ol>
    </>
  );
}
// 计划树
function PlaceTree({ id, parentId, placesById, onComplete }) {
  const place = placesById[id];
  const childIds = place.childIds;
  return (
    <li>
      {place.title}
      <button onClick={() => {
        onComplete(parentId, id);
      }}>
        Complete
      </button>
      {childIds.length > 0 &&
        <ol>
          {childIds.map(childId => (
            <PlaceTree
              key={childId}
              id={childId}
              parentId={id}
              placesById={placesById}
              onComplete={onComplete}
            />
          ))}
        </ol>
      }
    </li>
  );
}

https://react.docschina.org/learn/choosing-the-state-structure#avoid-deeply-nested-state

相关推荐
To_OC3 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
不好听6133 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus3 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端
前端小李子4 小时前
前端环境变量裸奔?我用 EnvShield 给它穿了件防弹衣
前端
youtootech4 小时前
HarmonyOS《柚兔学伴》项目实战25-我的页面、Web 嵌入与项目总结
前端·华为·harmonyos
小林ixn5 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
醇氧6 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展
窝子面7 小时前
手搓最简前后端协作-node
javascript·数据库
qetfw7 小时前
MXU:Tauri 2 + React 的 MaaFramework 跨平台 GUI 源码
前端·python·react.js·前端框架·开源项目·效率工具