在 redux-orm 模式实例上使用 reducer 方法
Use reducer method on redux-orm schema instance
我正在使用 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
})
大部分代码基于primer here
我的模型是这样的:
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
}
这是User模型,我在看到@squiroid原答案后添加了一个no-op reducer
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
}
据我从您的代码中可以看出,您似乎错过了在模型中定义减速器的代码 (TODO, TAG, USER)
。
根据文档 here。
您需要在每个模型中有一个静态方法。
static reducer(state, action, Tag)
static reducer(state, action, TODO)
static reducer(state, action, USER)
首先,我需要使用 ORM
而不是 Schema
。所以我将 Schema
的导入更改为:
import { ORM as Schema } from 'redux-orm'
其次,我不得不将减速器的签名更改为:
static reducer (action, SessionSpecificModel, session)
the redux-orm docs have been updated, the second argument is not the state of the reducer but a session specific model.
来自文档中的签名:
static reducer (state, action, Model, session)
第三,我不得不更改 todo
中的代码以使用 toRefArray
或 toModelArray
以便在 [=24= 的列表中调用 map
] 和 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
})
第四,我必须从 session
实例中解析 Model
class。
我仍然发现创建 Todo
的问题,其中:
session.Todo.create(props)
抛出 error
:
提供给 Todo.create
的道具 tags[0]
无效。
当使用 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 中引导或创建模型时,您可以将模型的 id 或实例提供给相关 属性。因此,确保两者都被 Model
.
接受是必要的
要进一步阅读有关从 redux-orm 0.8 迁移到 0.9 的信息,请查看开发人员的指南:
https://github.com/tommikaikkonen/redux-orm/wiki/0.9-Migration-Guide
github repo 上的 README 落后了,但令人惊讶的是 npm README 已更新为 0.9,尽管 0.9 的 PR 尚未合并。
https://www.npmjs.com/package/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
})
大部分代码基于primer here
我的模型是这样的:
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
}
这是User模型,我在看到@squiroid原答案后添加了一个no-op reducer
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
}
据我从您的代码中可以看出,您似乎错过了在模型中定义减速器的代码 (TODO, TAG, USER)
。
根据文档 here。
您需要在每个模型中有一个静态方法。
static reducer(state, action, Tag)
static reducer(state, action, TODO)
static reducer(state, action, USER)
首先,我需要使用 ORM
而不是 Schema
。所以我将 Schema
的导入更改为:
import { ORM as Schema } from 'redux-orm'
其次,我不得不将减速器的签名更改为:
static reducer (action, SessionSpecificModel, session)
the redux-orm docs have been updated, the second argument is not the state of the reducer but a session specific model.
来自文档中的签名:
static reducer (state, action, Model, session)
第三,我不得不更改 todo
中的代码以使用 toRefArray
或 toModelArray
以便在 [=24= 的列表中调用 map
] 和 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
})
第四,我必须从 session
实例中解析 Model
class。
我仍然发现创建 Todo
的问题,其中:
session.Todo.create(props)
抛出 error
:
提供给 Todo.create
的道具 tags[0]
无效。
当使用 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 中引导或创建模型时,您可以将模型的 id 或实例提供给相关 属性。因此,确保两者都被 Model
.
要进一步阅读有关从 redux-orm 0.8 迁移到 0.9 的信息,请查看开发人员的指南: https://github.com/tommikaikkonen/redux-orm/wiki/0.9-Migration-Guide
github repo 上的 README 落后了,但令人惊讶的是 npm README 已更新为 0.9,尽管 0.9 的 PR 尚未合并。 https://www.npmjs.com/package/redux-orm