Skip to content

Instantly share code, notes, and snippets.

@JoshuaCWebDeveloper
Created February 28, 2020 04:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshuaCWebDeveloper/25a302ec891acb6c4992fe137736160f to your computer and use it in GitHub Desktop.
Save JoshuaCWebDeveloper/25a302ec891acb6c4992fe137736160f to your computer and use it in GitHub Desktop.
Example for combining the redux-toolkit and redux-orm libraries
/*
* The redux-orm model and redux-toolkit slice are defined together in the same
* class.
* An export scheme similiar to Ducks is used, where the model class is
* exported in place of the reducer function.
*/
import { Model, fk, many, attr } from 'redux-orm';
import { createSlice } from '@reduxjs/toolkit';
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;
import React from "react";
import { render } from "react-dom";
import { configureStore } from "@reduxjs/toolkit";
import { Provider } from "react-redux";
import ormReducer from './ormReducer';
import App from "./components/App";
const store = configureStore({
orm: ormReducer,
});
// render() your React component with a <Provider />
import { ORM, createReducer } from 'redux-orm';
import Book from './models/Book';
import Author from './models/Author';
import Publisher from './models/Publisher';
const orm = new ORM({
stateSelector: state => state.orm,
});
orm.register(Book, Author, Publisher);
// use custom updater that calls slice reducer for each model
const ormReducer = createReducer(orm, function (session, action) {
session.sessionBoundModels.forEach(modelClass => {
if (typeof modelClass.slice.reducer === 'function') {
modelClass.slice.reducer(modelClass, action, session);
}
});
});
export default ormReducer;
export { orm };
@JoshuaCWebDeveloper
Copy link
Author

JoshuaCWebDeveloper commented Feb 28, 2020

@JoshuaCWebDeveloper
Copy link
Author

JoshuaCWebDeveloper commented Feb 28, 2020

In BookModel.js, I am using the stage 3 class fields and static class features proposals. Learn how to try them out using Babel here: https://babeljs.io/docs/en/babel-plugin-proposal-class-properties.

One can easily refactor the code to use the current syntax (Book.modelName = 'Book';) instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment