首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用redux工具箱重写redux-orm减速器

用redux工具箱重写redux-orm减速器
EN

Stack Overflow用户
提问于 2020-01-06 22:18:33
回答 3查看 1.3K关注 0票数 5

发行(tl;dr)

我们如何用redux-工具包createSlice创建一个createSlice

是否有一种比在这个问题中提供的尝试更简单、更建议、更优雅的解决方案?

详细信息

自定义剩馀量减速机的示例如下(简化):

代码语言:javascript
复制
function ormReducer(dbState, action) {
    const session = orm.session(dbState);
    const { Book } = session;

    switch (action.type) {
    case 'CREATE_BOOK':
        Book.create(action.payload);
        break;
    case 'REMOVE_AUTHOR_FROM_BOOK':
        Book.withId(action.payload.bookId).authors.remove(action.payload.authorId);
        break;
    case 'ASSIGN_PUBLISHER':
        Book.withId(action.payload.bookId).publisherId = action.payload.publisherId;
        break;
    }

    return session.state;
}

可以使用createSlice函数redux-工具包 (基于redux-toolkit 使用指南)简化还原器:

代码语言:javascript
复制
const ormSlice = createSlice({
  name: 'orm',
  initialState: [],
  reducers: {
    createBook(state, action) {},
    removeAuthorFromBook(state, action) {},
    assignPublisher(state, action) {}
  }
})
const { actions, reducer } = ormSlice
export const { createBook, removeAuthorsFromBook, assignPublisher } = actions
export default reducer

但是,在redux-orm还原器的开头,我们需要创建一个会话。

代码语言:javascript
复制
const session = orm.session(dbState);

然后我们使用还原器魔法,最后我们需要返回状态。

代码语言:javascript
复制
return session.state;

因此,我们忽略了添加此功能的beforeEachReducerafterEachReducer方法。

解决方案(尝试)

我们创建了一个withSession高阶函数,它创建会话并返回新状态。

代码语言:javascript
复制
const withSession = reducer => (state, action) => {
  const session = orm.session(state);
  reducer(session, action);
  return session.state;
}

我们需要在这个withSession中封装每个还原器逻辑。

代码语言:javascript
复制
import { createSlice } from '@reduxjs/toolkit';
import orm from './models/orm'; // defined elsewhere
// also define or import withSession here

const ormSlice = createSlice({
  name: 'orm',
  initialState: orm.session().state, // we need to provide the initial state
  reducers: {
    createBook: withSession((session, action) => {
      session.Book.create(action.payload);
    }),
    removeAuthorFromBook: withSession((session, action) => {
      session.Book.withId(action.payload.bookId).authors.remove(action.payload.authorId);
    }),
    assignPublisher: withSession((session, action) => {
      session.Book.withId(action.payload.bookId).publisherId = action.payload.publisherId;
    }),
  }
})

const { actions, reducer } = ormSlice
export const { createBook, removeAuthorsFromBook, assignPublisher } = actions
export default reducer
EN

回答 3

Stack Overflow用户

发布于 2020-01-07 16:40:30

这对我来说是一个有趣的问题,因为我创建了Redux工具包和我写了大量关于在我的“实用Redux”系列教程中使用Redux的文章。

从我的头上看,我不得不说您的withSession()包装器看起来是目前最好的方法。

同时,我不确定联合使用Redux和createSlice()是否真的能给您带来很多好处。您没有在内部使用Immer的不变更新功能,因为Redux正在处理模型中的更新。在这种情况下,唯一真正的好处是生成操作创建者和操作类型。

您最好单独调用createAction(),并在开关语句中使用生成的动作类型的原始还原器表单:

代码语言:javascript
复制
export const createBook = createAction("books/create");
export const removeAuthorFromBook = createAction("books/removeAuthor");
export const assignPublisher = createAction("books/assignPublisher");

export default function ormReducer(dbState, action) {
    const session = orm.session(dbState);
    const { Book } = session;

    switch (action.type) {
    case createBook.type:
        Book.create(action.payload);
        break;
    case removeAuthorFromBook.type:
        Book.withId(action.payload.bookId).authors.remove(action.payload.authorId);
        break;
    case assignPublisher.type:
        Book.withId(action.payload.bookId).publisherId = action.payload.publisherId;
        break;
    }

    return session.state;
}

我明白您所说的添加某种“前/后”处理程序的意思,但这会增加太多的复杂性。RTK旨在处理80%的用例,createSlice的TS类型已经非常复杂。在这里增加更多的复杂性将是不好的。

票数 5
EN

Stack Overflow用户

发布于 2020-02-28 05:02:16

我遇到了这个问题,希望将redux-工具包残存-orm的好处结合起来。我想出了一个解决方案,到目前为止我一直很满意。下面是我的redux-orm模型的样子:

代码语言:javascript
复制
class Book extends Model {

    static modelName = 'Book';

    // Declare your related fields.
    static fields = {
        id: attr(), // non-relational field for any value; optional but highly recommended
        name: attr(),
        // foreign key field
        publisherId: fk({
            to: 'Publisher',
            as: 'publisher',
            relatedName: 'books',
        }),
        authors: many('Author', 'books'),
    };

    static slice = createSlice({
      name: 'BookSlice',
      // The "state" (Book) is coming from the redux-orm reducer, and so will
      // never be undefined; therefore, `initialState` is not needed.
      initialState: undefined,
      reducers: {
        createBook(Book, action) {
            Book.create(action.payload);
        },
        removeAuthorFromBook(Book, action) {
            Book.withId(action.payload.bookId).authors.remove(action.payload.authorId);
        },
        assignPublisher(Book, action) {
            Book.withId(action.payload.bookId).publisherId = action.payload.publisherId;
        }
      }
    });

    toString() {
        return `Book: ${this.name}`;
    }
    // Declare any static or instance methods you need.

}

export default Book;
export const { createBook, removeAuthorFromBook, assignPublisher } = Book.slice.actions;

redux工具包片作为类上的静态属性创建,然后以类似于Ducks (ORMDucks?)的方式导出模型及其操作。

要做的唯一其他修改是为redux-orm还原器定义一个自定义更新程序:

代码语言:javascript
复制
const ormReducer = createReducer(orm, function (session, action) {
    session.sessionBoundModels.forEach(modelClass => {
        if (typeof modelClass.slice.reducer === 'function') {
            modelClass.slice.reducer(modelClass, action, session);
        }
    });
});

这里有一个更完整的例子:https://gist.github.com/JoshuaCWebDeveloper/25a302ec891acb6c4992fe137736160f

若干注记

  • @markerikson很好地指出了redux-工具箱的一些特性,因为redux-orm正在管理状态。对我来说,使用这种方法的两个最大好处是不必纠缠一大群行为创建者,也不必面对糟糕的switch语句:D。
  • 我正在使用的阶段3类字段和静态类的特点建议。(见https://babeljs.io/docs/en/babel-plugin-proposal-class-properties)。要使此ES6兼容,可以轻松地重构模型类,使用当前语法(即Book.modelName = 'Book';)定义其静态支持。
  • 如果您决定将上述模型与不定义slice的模型混合使用,则需要稍微调整createReducer更新程序中的逻辑。

对于一个真实的例子,看看我是如何在我的项目中使用这个模型的:https://github.com/vallerance/react-orcus/blob/70a389000b6cb4a00793b723a25cac52f6da519b/src/redux/models/OrcusApp.js。这个项目还处于初期阶段。我脑海中最大的问题是,这种方法的规模有多大;然而,我乐观地认为,随着项目的成熟,它将继续提供许多好处。

票数 4
EN

Stack Overflow用户

发布于 2020-04-22 17:53:54

尝试使用归一化减速器。它是一个高阶减缩器,它采用描述关系的模式,并返回根据关系写/读的还原器、动作和选择器。

它还容易与Normalizr和Redux工具包集成。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59619753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档