发行(tl;dr)
我们如何用redux-工具包的createSlice创建一个createSlice?
是否有一种比在这个问题中提供的尝试更简单、更建议、更优雅的解决方案?
详细信息
自定义剩馀量减速机的示例如下(简化):
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 使用指南)简化还原器:
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还原器的开头,我们需要创建一个会话。
const session = orm.session(dbState);然后我们使用还原器魔法,最后我们需要返回状态。
return session.state;因此,我们忽略了添加此功能的beforeEachReducer和afterEachReducer方法。
解决方案(尝试)
我们创建了一个withSession高阶函数,它创建会话并返回新状态。
const withSession = reducer => (state, action) => {
const session = orm.session(state);
reducer(session, action);
return session.state;
}我们需要在这个withSession中封装每个还原器逻辑。
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发布于 2020-01-07 16:40:30
这对我来说是一个有趣的问题,因为我创建了Redux工具包和我写了大量关于在我的“实用Redux”系列教程中使用Redux的文章。
从我的头上看,我不得不说您的withSession()包装器看起来是目前最好的方法。
同时,我不确定联合使用Redux和createSlice()是否真的能给您带来很多好处。您没有在内部使用Immer的不变更新功能,因为Redux正在处理模型中的更新。在这种情况下,唯一真正的好处是生成操作创建者和操作类型。
您最好单独调用createAction(),并在开关语句中使用生成的动作类型的原始还原器表单:
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类型已经非常复杂。在这里增加更多的复杂性将是不好的。
发布于 2020-02-28 05:02:16
我遇到了这个问题,希望将redux-工具包和残存-orm的好处结合起来。我想出了一个解决方案,到目前为止我一直很满意。下面是我的redux-orm模型的样子:
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还原器定义一个自定义更新程序:
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
若干注记
switch语句:D。Book.modelName = 'Book';)定义其静态支持。slice的模型混合使用,则需要稍微调整createReducer更新程序中的逻辑。对于一个真实的例子,看看我是如何在我的项目中使用这个模型的:https://github.com/vallerance/react-orcus/blob/70a389000b6cb4a00793b723a25cac52f6da519b/src/redux/models/OrcusApp.js。这个项目还处于初期阶段。我脑海中最大的问题是,这种方法的规模有多大;然而,我乐观地认为,随着项目的成熟,它将继续提供许多好处。
发布于 2020-04-22 17:53:54
尝试使用归一化减速器。它是一个高阶减缩器,它采用描述关系的模式,并返回根据关系写/读的还原器、动作和选择器。
它还容易与Normalizr和Redux工具包集成。
https://stackoverflow.com/questions/59619753
复制相似问题