Mobx 自动运行实践
Mobx Autorun in practice
我正在尝试让 Mobx 的自动运行正常工作。
我的用例是我有一个模型,我喜欢在它发生更改时对其进行序列化(或脱水),并将该信息添加到另一个模型的数据中。这给我带来了模型状态的基本时间旅行。两者都是可观察的。
编辑:模型分离的想法是,一个是应用程序的数据模型,另一个应该是我可以从应用程序中使用的完全独立的库。我需要定期跟踪应用程序的变化,但在同一页面上显示状态工具 UI。
现在,autorun 似乎对我实际跟踪的内容做出了自己的推断。当我将模型实例移动到观察模型的实例化中时,发生更改时不再调用自动运行。当在模块顶层创建模型实例时,它按我预期的那样工作。这是我只更改了一个 属性 观察模型(每次自动运行调用都会更改的那个)。当我尝试在观察模型中同时更改两件事时,现在也会为这些更改调用自动运行,导致无休止的循环(Mobx 捕获)。
我想知道如何更明确地表达我正在使用自动运行功能跟踪的内容,或者是否有其他方法可以跟踪模型更改并在发生任何事情时更新其他模型。
使用代码示例进行编辑。
这就是我所做的(大大简化):
class DataModel {
@observable one_state = null;
}
class StateStore {
@observable states = [];
}
let data = new DataModel();
let store = new StateStore();
autorun(() => {
store.states.push(data.one_state);
console.log("new data", toJSON(store.states));
});
data.one_state = "change 1";
data.one_state = "change 2";
这会产生循环依赖,因为 原始数据模型更改和由此产生的存储更改都会调用自动运行,而我只对跟踪前者的更改感兴趣。
编辑工作结果:
class DataModel {
@observable one_state = null;
}
class StateStore {
@observable states = asFlat([]);
}
let data = new DataModel();
let store = new StateStore();
autorun(() => {
store.states.push(data.one_state);
});
data.one_state = "change 1";
data.one_state = "change 2";
根据@mweststrate 的回答,将 asFlat 与商店的状态变量一起使用并从自动运行中删除日志记录打破了问题循环。
如果没有真正的代码,很难回答这个问题。你能分享一些代码吗?但请注意,如果你稍微改变一下想法,MobX 的效果最好:与其强制说 "if X happens Y should be changed",不如说 "Y can be derived from X"。如果您按照这些思路思考,MobX 将真正开始大放异彩。
因此,与其拥有两个可观察模型,我认为其中一个应该是另一个的推导(通过使用 computed indeed)。那有意义吗?否则,请随时详细说明您的问题:)
编辑:
好的,谢谢你的代码。您应该删除日志语句以避免循环;当前您记录状态模型,因此每次更改时,auto运行 将 运行、添加第一项(再次!)、更改 stateModel 等...
其次,我不确定状态列表是否应该是可观察的,但至少它的内容不应该是可观察的(因为它是一个快照,每个状态的数据不应该改变)。为了表达这一点,您可以使用 asFlat
修饰符,它表示 states 集合应该只能被浅层观察到:@observable states = asFlat([])
.
这是否回答了您的问题?
我正在尝试让 Mobx 的自动运行正常工作。
我的用例是我有一个模型,我喜欢在它发生更改时对其进行序列化(或脱水),并将该信息添加到另一个模型的数据中。这给我带来了模型状态的基本时间旅行。两者都是可观察的。
编辑:模型分离的想法是,一个是应用程序的数据模型,另一个应该是我可以从应用程序中使用的完全独立的库。我需要定期跟踪应用程序的变化,但在同一页面上显示状态工具 UI。
现在,autorun 似乎对我实际跟踪的内容做出了自己的推断。当我将模型实例移动到观察模型的实例化中时,发生更改时不再调用自动运行。当在模块顶层创建模型实例时,它按我预期的那样工作。这是我只更改了一个 属性 观察模型(每次自动运行调用都会更改的那个)。当我尝试在观察模型中同时更改两件事时,现在也会为这些更改调用自动运行,导致无休止的循环(Mobx 捕获)。
我想知道如何更明确地表达我正在使用自动运行功能跟踪的内容,或者是否有其他方法可以跟踪模型更改并在发生任何事情时更新其他模型。
使用代码示例进行编辑。
这就是我所做的(大大简化):
class DataModel {
@observable one_state = null;
}
class StateStore {
@observable states = [];
}
let data = new DataModel();
let store = new StateStore();
autorun(() => {
store.states.push(data.one_state);
console.log("new data", toJSON(store.states));
});
data.one_state = "change 1";
data.one_state = "change 2";
这会产生循环依赖,因为 原始数据模型更改和由此产生的存储更改都会调用自动运行,而我只对跟踪前者的更改感兴趣。
编辑工作结果:
class DataModel {
@observable one_state = null;
}
class StateStore {
@observable states = asFlat([]);
}
let data = new DataModel();
let store = new StateStore();
autorun(() => {
store.states.push(data.one_state);
});
data.one_state = "change 1";
data.one_state = "change 2";
根据@mweststrate 的回答,将 asFlat 与商店的状态变量一起使用并从自动运行中删除日志记录打破了问题循环。
如果没有真正的代码,很难回答这个问题。你能分享一些代码吗?但请注意,如果你稍微改变一下想法,MobX 的效果最好:与其强制说 "if X happens Y should be changed",不如说 "Y can be derived from X"。如果您按照这些思路思考,MobX 将真正开始大放异彩。
因此,与其拥有两个可观察模型,我认为其中一个应该是另一个的推导(通过使用 computed indeed)。那有意义吗?否则,请随时详细说明您的问题:)
编辑:
好的,谢谢你的代码。您应该删除日志语句以避免循环;当前您记录状态模型,因此每次更改时,auto运行 将 运行、添加第一项(再次!)、更改 stateModel 等...
其次,我不确定状态列表是否应该是可观察的,但至少它的内容不应该是可观察的(因为它是一个快照,每个状态的数据不应该改变)。为了表达这一点,您可以使用 asFlat
修饰符,它表示 states 集合应该只能被浅层观察到:@observable states = asFlat([])
.
这是否回答了您的问题?