Недавно я начал использовать MobX и наткнулся на концепцию reaction
. Я понимаю reactions
как функции, вызывающие побочные эффекты. Каковы побочные эффекты - решать мне. Я использую реакцию, чтобы обновить состояние MobX. Если вы посмотрите мой код ниже, у меня есть состояние для предметов (ингредиентов). Что я хочу сделать, так это загрузить ингредиенты из моего локального хранилища (функция getIngredients
) и отобразить их в моем React. Все идет нормально. Затем, когда я обновляю ингредиент (меняю имя, цену, вес - это можно редактировать по форме), я хочу сохранить это изменение в localStorage (функция putIngredient
), а затем соответствующим образом обновить свой @observable ingredients
(так позже, когда я избавлюсь от localStorage
и заменяю его базой данных, я отслеживаю свои изменения в MobX). Я думал, что использование MobX reaction
- это неплохая идея, как с этим справиться, но когда я попытался запустить функцию updateIngredients
, я получил следующую ошибку:
Encountered an uncaught exception that was thrown by a reaction or observer component, in: 'Reaction[Reaction@1]' Error: "ingredients" is read-only
Вы можете видеть, что внутри функции updateIngredients
есть одна прокомментированная строка. Если я раскомментирую эту строку и закомментирую предыдущую (ingredients = ingredients.map(i => i.id === ingredient.id ? ingredient : i);
), скрипт заработает. Я подумал, что могу редактировать observable
переменные, просто переназначив им новые значения. Собственно, я уже так делал в функции getIngredients
, где функция getIngredients
возвращает новый массив. Так в чем же здесь фокус? Почему я получаю эту ошибку?
import { observable, action, reaction } from 'mobx';
import { getIngredients, putIngredient } from './localStorage';
class Ingredients {
@observable ingredients = [];
@observable updatedIngredient = null;
@action.bound getIngredients(opts = {}) {
this.ingredients = getIngredients({ ...opts });
}
@action.bound async putIngredient(ingredient) {
putIngredient(ingredient);
this.updatedIngredient = ingredient;
}
@action.bound updateIngredients(ingredient) {
const { ingredients } = this;
ingredients = ingredients.map(i => i.id === ingredient.id ? ingredient : i);
// ingredients.replace(ingredients.map(i => i.id === ingredient.id ? ingredient : i));
}
}
const IngredientsStore = new Ingredients();
reaction(
() => IngredientsStore.updatedIngredient,
(updatedIngredient) => {
if (updatedIngredient) {
IngredientsStore.updateIngredients(updatedIngredient);
}
}
)
export default IngredientsStore;
{ ingredients } = this
в функцииupdateIngredients
и используюthis.ingredients = this.ingredients.map(...)
, скрипт работает должным образом. - person exoslav   schedule 05.03.2020