Я недавно начал использовать MobX и натолкнулся на концепцию reaction
. Я понимаю reactions
как функции, которые запускают побочные эффекты. Это зависит от меня, каковы побочные эффекты. Я использую реакцию, чтобы обновить свое состояние MobX. Если вы проверите мой код ниже, у меня есть состояние для предметов (ингредиенты). Что я хочу сделать, это загрузить ингредиенты из моего localStorage (функция 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;