Created
February 28, 2020 04:13
-
-
Save JoshuaCWebDeveloper/25a302ec891acb6c4992fe137736160f to your computer and use it in GitHub Desktop.
Example for combining the redux-toolkit and redux-orm libraries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
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
For a real world example, see: https://github.com/vallerance/react-orcus/blob/70a389000b6cb4a00793b723a25cac52f6da519b/src/redux/models/OrcusApp.js