Как я могу наблюдать какие-либо изменения (свойство добавлено, удалено или изменено) на наблюдаемой карте MOBX? - PullRequest
0 голосов
/ 06 февраля 2019
class FilterCriteria {
    @observable filter = new Map();
}

let criteria = new FilterCriteria ();

// setting up a reaction when something in the filter changes
// (property added, removed, or changed)
reaction(()=>criteria.filter, data => console.log(data.toJSON()));

criteria.filter.set('name', 'John'); // setting a new property.

Я ожидаю, что вышеприведенный код напечатает { 'name': 'John' }, но похоже, что реакция не запущена.

Я подозреваю, что неправильно настроил реакцию.Я хочу реагировать на каждое добавление нового ключа, удаление существующего ключа или изменение значения ключа.Я не знаю ключей или значений во время компиляции.

Как мне это сделать?

ОБНОВЛЕНИЕ

Я изменил свой код на

class FilterCriteria {
    @observable filter = new Map();
    @computed get json(){ return this.filter.toJSON(); }
}
...
reaction(()=>criteria.json, data => console.log(data));

и теперь, похоже, работает правильно.Побочный эффект реакции выполняется всякий раз, когда я добавляю, удаляю или изменяю значение на карте.

Таким образом, вопрос заключается в том, почему реакция была выполнена во втором, а не в первом примере?

ОБНОВЛЕНИЕ2

Я снова изменил свой код во второй раз.Я вернулся почти к первой версии, но на этот раз вместо того, чтобы реагировать на criteria.filter и регистрировать data.toJSON(), я реагирую на criteria.filter.toJSON() и регистрирую data (toJSON перемещается от побочного эффекта к наблюдаемому значению).На этот раз реакция проходит нормально.

class FilterCriteria {
    @observable filter = new Map();
}

reaction(()=>criteria.filter.toJSON(), data => console.log(data));

Опять же, я не понимаю, почему.Если criteria.filter не является наблюдаемым само по себе, то каким образом отслеживаемое выражение переоценивается, когда что-то внутри crit.filter изменяется?

ОБНОВЛЕНИЕ 4 (надеюсь, последнее) РЕШЕНИЕ

Согласно документации MobX, mobx реагирует на любое существующее наблюдаемое свойство, которое читается во время выполнения отслеживаемой функции.

Побочный эффект реакции выполняется, когда наблюдаемое свойство изменения .В моем примере при реакции на criteria.filter читаемое здесь наблюдаемое свойство равно filter, но сам фильтр никогда не изменяется.Это одна и та же карта всегда.Это свойства фильтра, которые меняются.Поэтому реакция никогда не запускается для criteria.filter.

Но когда я реагирую на criteria.filter.toJSON() или mobx.toJS(criteria.filter), реакция выполняется правильно.

Так почему же это так?criteria.filter не изменяется, а toJSON не является наблюдаемым свойством.Это функция.то же самое для mobx.toJS.Кажется, здесь нет никаких свойств.Но это не правильно.Как говорится в документации (но не так сильно), свойства attribute.filter действительно читаются при выполнении toJSON или mobx.toJS, потому что обе функции создают глубокий клон карты (таким образом, перебирая каждое свойство).

Теперь, в начале, Карта не содержала никаких свойств.Итак, как же отслеживаются вновь добавленные свойства, поскольку они не существовали (для чтения), когда началось отслеживание?Это особенность карты.Карты обеспечивают наблюдаемость и для еще не существующих свойств.

В MobX 5 вы также можете отслеживать несуществующие свойства наблюдаемых объектов (не экземпляров классов), при условии, что они были закреплены наблюдаемыми или наблюдаемыми.object.Экземпляры класса не поддерживают это.

1 Ответ

0 голосов
/ 06 февраля 2019

В mobx у вас есть два варианта, когда вы хотите наблюдать изменения в чем-то, что можно наблюдать.reaction и observe.Reaction позволяет указать, когда вы хотите, чтобы какая-то функция вызывалась, когда изменяется конкретный аспект наблюдаемого.Это могут быть изменения длины массива, ключей, свойств, что угодно.observe вызовет некоторую функцию каждый раз, когда наблюдаемое изменилось.

Я подозреваю, что причина, по которой ваша реакция не была вызвана, связана с первой функцией.() => criteria.filter.Это не будет срабатывать при добавлении / удалении ключа или изменении значения.Вместо этого он будет срабатывать, когда filter действительно изменится.А поскольку filter действительно является ссылкой на Карту, она никогда не изменится, даже если сама Карта изменится.

Вот несколько примеров, иллюстрирующих мою точку зрения:

Если вы хотитевызвать реакцию, когда ключ был добавлен или удален, вы можете захотеть, чтобы ваша функция была:

() => criteria.filter.keys()

Результат этой функции будет другим, когда ключ был добавлен илиудален.Точно так же, если вы хотите вызвать реакцию, когда значение было изменено, должно сработать что-то вроде этого:

() => criteria.filter.values()

Так что некоторая комбинация этих двух должна быть именно тем, что вам нужнослушать изменения ключей / значений.В качестве альтернативы вы можете использовать observe, который будет срабатывать при каждом изменении и требовать от вас проверки того, что изменилось, чтобы убедиться, что ваши конкретные условия были выполнены, чтобы гарантировать вызов функции (т. Е. Изменение ключа / значения)

ОБНОВЛЕНИЕ: Вот пример, который иллюстрирует проблему

@observable map = new Map();

Позволяет сказать, что значение карты в памяти равно 5. Поэтому, когда вы проверяете map === map, это эквивалентно 5 === 5 и будет оцениваться как true.

Теперь, глядя на первый фрагмент кода, который вы разместили:

reaction(() => map, data => console.log(map.toJSON()));

Каждый раз, когда выдобавить / удалить ключ или изменить значение, эта первая функция будет запущена.И результат будет 5, так как это то, что мы сказали, значение в памяти для этого примера.Он скажет: старое значение 5, а новое значение 5, поэтому никаких изменений нет.Поэтому реакция не запустит вторую функцию.

Теперь второй фрагмент:

reaction(() => map.toJSON(), data => console.log(data));

Сначала результат функции будет: {}потому что карта пуста.Теперь давайте добавим ключ:

map.set(1, 'some value');

Теперь результат первой функции будет:

{"1": "some value"}

Понятно, что этозначение отличается от {}, поэтому что-то изменилось, и называется вторая функция реакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...