gpt4 book ai didi

reactjs - Redux 如何在嵌套属性上使用 createEntityAdapter?

转载 作者:行者123 更新时间:2023-12-03 20:48:33 26 4
gpt4 key购买 nike

我正在使用 React/Redux 创建一个应用程序,我是使用 React 和 Redux 的新手。我一直在试图弄清楚如何构建 redux 存储。这是我想要实现的目标的简要描述,使用 redux createEntityAdapter 文档中的书籍示例进行概括
我有一个包含书籍 list 的页面。用户可以单击一本书或多本书,并为每本书显示一个章节列表。新的或缺失的章节可以在服务器上可用时随时添加。添加的章节需要添加到列表中的正确位置。

  • 第一册
  • 第1章
  • 第2章
  • 第3章
  • 第6章

  • 第2册
  • 第3册

  • 书单是一个组件,章节列表是另一个组件,但是由于书多,章节列表组件的实例也会很多。每个组件都有自己的切片。
    店铺长这样:
    bookList : [ Book1, Book2, Book3, ...]
    ChapterList: {
    Book1 : {
    chapters: [
    {
    Chapter : 'Chapter1',
    info: 'Chapter info',
    other: 'more stuff'
    },
    {
    Chapter : 'Chapter2',
    info: 'Chapter info',
    other: 'more stuff'
    },
    {...}
    ],
    bookInfo: 'info about book'
    },
    Book2 : { ... },
    Book3 : { ... }
    }

    问题是章节信息正在流式传输,因此会不断更新,丢失的章节可以随时到达。因此,每次新数据到达时我都需要对章节数组进行排序,而该数组不是很长,以 50 个元素的顺序,新数据每秒到达几次。
    我打算使用 createEntityAdapter 来规范化章节数组,但我不知道这是怎么可能的,因为它嵌套在 Book# 属性中,并且需要 Book# 属性,因为我使用了 ChapterList 组件的多个实例。
    const ChapterListAdapter = createEntityAdapter({
    // where bookNum needs to Book1, Book2, Book3 etc...
    selectId: (chapterList) => chapterList[bookNum].chapters,

    sortComparer: (a, b) => a.chapters.localeCompare(b.chapters
    })
    我该如何解决这个问题?修改店铺?有没有办法展平chapterList,使章节处于顶层?我是否将自己的规范化/排序逻辑写入 reducer ?

    最佳答案

    Is there a way to flatten chapterList such that chapters is at the top level? Do I write my own normalizing/sorting logic into the the reducer?


    您可以在 Normalizing State Shape 上查看 Redux 指南作为起点。
    这里有两个实体:“书籍”和“章节”。它们之间存在一种关系:每一章都属于一本书,每本书都包含一个有序的章节列表。您需要两个实体适配器。你可以用一两片——用两片可能更容易,但没关系。
    您标准化的状态形状应如下所示:
    {
    books: {
    ids: [1, 2, 3],
    entities: {
    1: {
    id: 1,
    title: "Book 1",
    bookInfo: 'info about book',
    chapterIds: [75, 962, 64], // an ordered array of chapters
    },
    2: { /* ... */ },
    3: { /* ... */ }
    }
    },
    chapters: {
    ids: [64, 75, 962],
    entities: {
    64: {
    id: 64,
    name: "Some Chapter Title",
    info: "",
    other: "",
    bookId: 1 // the id of the book that this chapter belongs to
    },
    75: { /* ... */ },
    962: { /* ... */ }
    }
    }
    }
    在 typescript 方面:
    import { EntityState, EntityId } from "@reduxjs/toolkit";

    export interface Book {
    id: EntityId;
    title: string;
    bookInfo: string;
    chapterIds: EntityId[];
    }

    export interface Chapter {
    id: EntityId;
    name: string;
    info: string,
    other: string;
    bookId: EntityId;
    }

    interface State {
    books: EntityState<Book>;
    chapters: EntityState<Chapter>;
    }

    我很难在不知道数据来自服务器时的形状的情况下编写您的 reducer 。看你一一介绍的章节,好像已经正常化了?

    我更容易编写组件。我们有选择器从 id 中选择完整的实体对象:
    const bookAdapter = createEntityAdapter<Book>();

    const chapterAdapter = createEntityAdapter<Chapter>();

    export const {
    selectIds: selectBookIds,
    selectById: selectBookById
    } = bookAdapter.getSelectors((state: State) => state.books);

    export const {
    selectById: selectChapterById
    } = chapterAdapter.getSelectors((state: State) => state.chapters);
    所以每个组件需要的唯一 Prop 是 id :
    const Chapter = ({ id }: { id: EntityId }) => {
    const chapter = useSelector((state) => selectChapterById(state, id));

    // probably some hook here to request the chapter if not loaded
    // dispatch an async thunk inside of a useEffect

    if (!chapter) {
    return <Loading />;
    }

    return (
    <div>
    <h3>{chapter.name}</h3>
    <p>{chapter.info}</p>
    </div>
    );
    };

    const Book = ({ id }: { id: EntityId }) => {
    const book = useSelector((state) => selectBookById(state, id));

    // probably some hook here to request the book if not loaded
    // dispatch an async thunk inside of a useEffect

    if (!book) {
    return <Loading />;
    }

    return (
    <div>
    <h1>{book.title}</h1>
    <p>{book.bookInfo}</p>
    <h2>Chapters</h2>
    <ul>
    {book.chapterIds.map((chapterId) => (
    <li key={chapterId}>
    <Chapter id={chapterId} />
    </li>
    ))}
    </ul>
    </div>
    );
    };
    您可以 check out this answer有关如何仅在尚未加载实体时从 API 请求实体的更多信息。

    关于reactjs - Redux 如何在嵌套属性上使用 createEntityAdapter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64269690/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com