我有3个来自Record的类。前两个类的定义如下。
// Base.js
import {Record} from 'immutable';
import * as uuid from 'uuid';
export const Base = defaultValues => {
return class extends Record({
key: null,
...defaultValues,
}) {
constructor(props) {
super(Object.assign({}, props, {key: (props && props.key) || uuid.v4()}));
}
};
};
// LOBase.js
import {Base} from './BaseModel';
export const LOBase = defaultValues => {
return class extends Base({
created_at: new Date(null),
updated_at: new Date(null),
deleted_at: new Date(null),
isActive: new Boolean(),
isDeleted: new Boolean(),
publishState: new String(),
...defaultValues,
}) {};
};
这是我从LOBase派生的最后一个类,我的问题出在那里。
// Question.js
import {List, Record, fromJS} from 'immutable';
import _ from 'lodash';
import {LOBase} from './base/LOBaseModel';
export class Question extends LOBase({
id: '',
name: 'test',
description: '',
questionType: 1,
title: 'title',
version: new String(),
customData: {},
//...
}) {
insertOption() {
let index = this.customData.options.length;
this.updateIn(['customData', 'options'], options => {
return options.splice(index, 0, {
someGenericStuff: [],
// ...
});
});
return this;
}
static MultipleChoice() {
let defaultCustomData = {
options: [],
//...
};
let question = new Question()
.set('questionType', QUESTION_TYPE_MULTIPLE_CHOICE)
.set('customData', new Record(defaultCustomData)())
//...
.insertOption()
.insertOption()
.insertOption();
return question;
}
// ...
}
我使用let question = Question.MultipleChoice()
创建一个新的Question实例。当我使用question.insertOption()
时它工作正常。但是,当我在状态的reducer中执行此操作时,我收到错误消息“在调度中检测到状态突变”。
如何在州内更改问题对象?我应该在这之前克隆原始记录吗? Immutablejs的做法是什么?
提前致谢。
答案 0 :(得分:0)
insertOption使用this.updateIn但不返回或存储结果。 当您在函数末尾返回 this 时,实际上会返回相同的不可变记录而不进行更改。 所以,除非我在这里遗漏了什么,否则你应该选择:
insertOption() {
let index = this.customData.options.length;
return this.updateIn(['customData', 'options'], options => {
return options.splice(index, 0, {
someGenericStuff: [],
// ...
});
});
}
updateIn将返回带有更新值的Record的新实例。
你没有添加你的状态结构和reducer(如果可以的话),但你应该确保每次返回一个新的状态对象,而不仅仅是更改问题字段。
顺便说一下,你是一个接一个地做一系列变异方法(set,set,updateIn)。从性能角度来看,这是不可取的。我建议用以下方式用withMutations替换它:static insertOption(record) {
let index = record.customData.options.length;
return record.updateIn(['customData', 'options'], options => {
return options.splice(index, 0, {
someGenericStuff: [],
// ...
});
});
}
static MultipleChoice() {
// ...
let question = new Question();
question.withMutations(record => {
record.merge({
questionType: QUESTION_TYPE_MULTIPLE_CHOICE,
customData: new Record(defaultCustomData)()
})
Question.insertOption(record);
})
return question;
}