У меня есть магазин mobx, который выглядит как
class EntityStore {
rootStore
@observable entityIndex = {}
constructor(rootStore){
this.rootStore = rootStore;
}
@action addEntities(entityArray){
entityArray.forEach((entity) => this.addEntity(entity));
}
@action addEntity(entityProps){
if(entityProps.id && this.entityIndex[entityProps.id]){
throw new Error(`Failed to add ${entityProps.id} an entity with that id already exists`);
}
const entity = new Entity({
...entityProps,
assetStore: this.rootStore.assetStore,
regl,
});
this.entityIndex[entity.id] = entity;
}
@computed get entityAssetIds(){
return Object.values(this.entityIndex).map(e => e.assetId);
}
@computed get renderPayload(){
const payloadArray = [];
for(let entityId in this.entityIndex){
payloadArray.push(this.entityIndex[entityId].renderPayload)
}
return payloadArray;
}
}
Это дорогостоящее вычисляемое значение с дочерними вычисляемыми значениями, которое вызывается в цикле requestAnimationFrame
, который вызывает entityStore.renderPayload()
со скоростью 60 кадров в секунду. Мне нужно, чтобы это было кэшировано.
используя trace
, я получил результат [mobx.trace] '[email protected]' is being read outside a reactive context. Doing a full recompute
Это удивительно для меня, поскольку я ожидал, что Mobx будет пересчитывать только в том случае, если зависимые наблюдаемые для вычисляемого значения изменятся.
Есть ли способ заставить это поведение без пересчета?
Обновление: я не использую реакцию. это простые объекты mobx. Я создал пример воспроизведения на https://github.com/kevzettler/mobx_bad/< /а> похоже
class ShouldMemoize {
@observable position = 0
staticValue = 200;
@computed get expensiveStaticOperation(){
console.log('this is expensive and should not recompute');
return this.staticValue*2;
}
@computed get output(){
return this.position + this.expensiveStaticOperation;
}
@action incrementPosition(val){
this.position+= 1;
}
}
let M = new ShouldMemoize();
console.log('**********start*********');
setInterval(() =>{
M.incrementPosition();
console.log(
"*tick*",
M.output
);
}, 60)
В этом примере демонстрируется вычисляемый метод expensiveStaticOperation
, на который ссылается другой вычисляемый метод output
. метод output
вызывается через короткие промежутки времени, и вывод журнала указывает, что затем также вызывается expensiveStaticOperation
и пересчитывается на каждом такте. Я ожидаю, что, поскольку зависимые значения expensiveStaticOperation
не меняются, они будут запоминаться, а не выполняться повторно.