Использовать метод редуктора в экземпляре схемы redux-orm
Я использую Redux-Orm для создания моделей для нормализации и денормализации. Я обнаружил, что при создании схемы я получаю сообщение об ошибке:
Uncaught Error: Schema has been renamed to ORM. Please import ORM instead of Schema from Redux-ORM
Я использовал оба 0.90-rc1
какая версия установлена по умолчанию, а также `0.8.4
при запуске этого кода:
import { Schema } from 'redux-orm'
import Todo from './Todo'
import Tag from './Tag'
import User from './User'
const schema = new Schema()
schema.register(Todo, Tag, User)
export default schema
Однако я нахожу, что документация и код для схем в redux-orm все еще существуют.
Если я переключусь с
import { Schema } from 'redux-orm'
в
import { ORM as Schema } from 'redux-orm'
код работает, но я получаю сообщение об ошибке, указывающее, что reducer
метод не определен здесь:
import { schema } from './models'
console.log(schema)
const rootReducer = combineReducers({
orm: schema.reducer(),
selectedUserId: selectedUserIdReducer
})
Большая часть кода основана на учебнике
Мои модели выглядят так:
ValidatingModel.js
import { PropTypes } from 'react'
import { Model } from 'redux-orm'
import propTypesMixin from 'redux-orm-proptypes'
const ValidatingModel = propTypesMixin(Model)
export default ValidatingModel
Todo.js
import { fk, many } from 'redux-orm'
import { PropTypes } from 'react'
import ValidatingModel from './ValidatingModel'
import User from './User'
import Tag from './Tag'
import { CREATE_TODO, MARK_DONE, DELETE_TODO, ADD_TAG_TO_TODO, REMOVE_TAG_FROM_TODO } from '../actionTypes'
export default class Todo extends ValidatingModel {
static reducer (state, action, Todo, session) {
const { payload, type } = action
switch (type) {
case CREATE_TODO:
const tagIds = payload.tags.split(',').map(str => str.trim())
const props = Object.assign({}, payload, { tags: tagIds })
Todo.create(props)
break
case MARK_DONE:
Todo.withId(payload).set({ done: true })
break
case DELETE_TODO:
Todo.withId(payload).delete()
break
case ADD_TAG_TO_TODO:
Todo.withId(payload.todo).tags.add(payload.tag)
break
case REMOVE_TAG_FROM_TODO:
Todo.withId(payload.todo).tags.remove(payload.tag)
break
}
}
}
Todo.modelName = 'Todo'
Todo.propTypes = {
id: PropTypes.number,
text: PropTypes.string.isRequired,
done: PropTypes.bool.isRequired,
user: PropTypes.oneOf([PropTypes.instanceOf(User), PropTypes.number]),
tags: PropTypes.arrayOf(PropTypes.oneOf([
PropTypes.number,
PropTypes.instanceOf(Tag)
]))
}
Todo.defaultProps = {
done: false
}
Todo.fields = {
user: fk('User', 'todos'),
tags: many('Tag', 'todos')
}
Tag.js
import ValidatingModel from './ValidatingModel'
import { PropTypes } from 'react'
import { CREATE_TODO, ADD_TAG_TO_TODO } from '../actionTypes'
export default class Tag extends ValidatingModel {
static reducer (state, action, Tag, session) {
const { payload, type } = action
switch (type) {
case CREATE_TODO:
const tags = payload.tags.split(',')
const trimmed = tags.map(name => name.trim())
trimmed.forEach(name => Tag.create(name))
break
case ADD_TAG_TO_TODO:
if (!Tag.filter({ name: payload.tag }).exists()) {
Tag.create({ name: payload.tag })
}
break
}
}
}
Tag.modelName = 'Tag'
Tag.backend = {
idAttribute: 'name'
}
Tag.propTypes = {
name: PropTypes.string
}
Это модель пользователя, я добавил неоперативный редуктор, увидев оригинальный ответ @squiroid
import ValidatingModel from './ValidatingModel'
import { PropTypes } from 'react'
export default class User extends ValidatingModel {
static reducer (state, action, User, session) {
return state
}
}
User.modelName = 'User'
User.propTypes = {
id: PropTypes.number,
name: PropTypes.string
}
3 ответа
Во-первых, мне нужно было использовать ORM
вместо Schema
, Поэтому я изменил импорт для Schema
чтобы:
import { ORM as Schema } from 'redux-orm'
Во-вторых, мне пришлось изменить сигнатуру редуктора на:
static reducer (action, SessionSpecificModel, session)
Документы Redux-Orm обновлены, вторым аргументом является не состояние редуктора, а конкретная модель сеанса.
из подписи в документации:
static reducer (state, action, Model, session)
В-третьих, мне пришлось изменить код в todo
использовать toRefArray
или же toModelArray
для того, чтобы позвонить map
в списке Todo
а также Tag
экземпляры:
return orm.Todo.filter({ user: userId }).toModelArray().map(todo => {
const obj = Object.assign({}, todo.ref)
obj.tags = todo.tags.toRefArray().map(tag => tag.name)
return obj
})
В-четвертых, я должен был решить Model
класс от session
пример.
Я все еще нахожу проблемы с созданием Todo
где:
session.Todo.create(props)
бросает error
:
Неверная опора tags[0]
поставляется в Todo.create
,
когда вызывается с props
:
{
"text":"Test my data",
"tags":[
"urgent",
"personal"
],
"user":0
}
Проверки, кажется, мешают созданию модели. При создании тегов укажите PropTypes
быть:
const { string, number, arrayOf oneOfType, instanceOf } = PropTypes
Todo.propTypes = {
text: string,
user: oneOfType([
number,
instanceOf(User)
]),
tags: oneOfType([
arrayOf(string),
arrayOf(
instanceOf(Tag)
)
])
}
В redux-orm при начальной загрузке или создании моделей вы можете указать идентификатор или экземпляр модели для связанного свойства. Таким образом, было бы необходимо обеспечить, чтобы оба Model
,
Насколько я вижу из вашего кода, кажется, что вы пропустили код определения редуктора в ваших моделях (TODO, TAG, USER)
,
Согласно документации здесь.
Вам нужно иметь один статический метод внутри каждой модели.
static reducer(state, action, Tag)
static reducer(state, action, TODO)
static reducer(state, action, USER)
Для получения дополнительной информации о переходе с redux-orm 0.8 на 0.9 ознакомьтесь с этим руководством разработчика: https://github.com/tommikaikkonen/redux-orm/wiki/0.9-Migration-Guide
README на репозитории github отстает, но на удивление npm README обновляется до 0,9, несмотря на то, что PR для 0,9 еще не слился. https://www.npmjs.com/package/redux-orm