Mobx - изменить наблюдаемый массив внутри реакции - PullRequest
0 голосов
/ 05 марта 2020

Я недавно начал использовать 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...