Как стать автором
Обновить

Комментарии 24

С приходом 6 версии перестали быть нужны классы и декораторы. И то, и другое я считаю ненужным и даже вредным синтаксическим сахаром

Классы и декораторы никогда не были в MobX'e обязательным условием, все точно так же можно было использовать через observable({ test: 1 }) и т.п.

Но как бы с классами и декораторами намного удобнее, приятнее и читаемее.

Оборачивание компонентов в observer HOC для добавления им реактивности

Как бы решается просто и надежно:
import * as React from 'react';
import { observer } from 'mobx-react';
import { configure } from 'mobx';

const wrappedComponentsSet = new WeakSet();
const wrappedComponentsMap = new WeakMap();

// @ts-ignore
const createElement = React.createElement;
// @ts-ignore
React.createElement = function() {
    const target = arguments[0];

    if (typeof target === 'function' && !wrappedComponentsSet.has(target)) {
        if (target.prototype.shouldComponentUpdate) {
            delete target.prototype.shouldComponentUpdate;
        }

        wrappedComponentsSet.add(target);
        const wrapped = observer(target);
        arguments[0] = wrapped;
        wrappedComponentsMap.set(target, wrapped);
    } else if (wrappedComponentsSet.has(target)) {
        arguments[0] = wrappedComponentsMap.get(target) || observer(target);
    }
    return createElement.apply(this, arguments)
};


И теперь просто пишем
export function MyComponent() {
    return <div>{userState.email}</div>;
}

И все работает и все реактивное.

MobX — достойный менеджер состояния

Это единственное, безальтернативное и лучшее из доступных на сегодня решений, чтобы можно было работать с React'ом без боли и страданий.

Зачем манкипатчить реакт, потенциально ломая сторонние компоненты, если можно зарегистрировать кастомную jsx фабрику?

Зачем манкипатчить реакт, потенциально ломая сторонние компоненты, если можно зарегистрировать кастомную jsx фабрику?

Если сторонний компонент сломается от HOC'a observer, то это похоже кривой компонент и я бы задумался о его использовании)

Я тоже патчил React.createElemnt схожим образом для того, чтобы автоматом все компоненты были observerver'ами, заодно автоматом заворачивал компоненты в ErrorBoundary чтобы вся страница не падала, а падал только конкретный компонент в котором возникла ошибка, и он показывал текст «Something went wrong».
Проблем не было ни разу с этим. в том числе со сторонним ant-design.

Пишешь чистый код и не думаешь об этих обертках, просто всё работает.

Вы может быть ещё и ремнём безопасности в автомобиле не пользуетесь, ибо "всегда прокатывало"?

Вы так говорите, как будто это какая-то проблема. Лично у меня 2 года работает эта штука в разных проектах и чувствует себя великолепно. Если вдруг произойдет немыслимое и оборачивание стороннего компонента в observer его сломает, и вот нужно именно его использовать, то можно зарегистрировать JSX фабрику кастомную и там это провернуть или добавить условие на проверку компонента по ссылке, и если его не надо заворачивать, то просто не заворачиваем, какие проблемы то?

Вы развели несуществующую «проблему» на ровном месте, смысл?
Я предпочитаю хороший и чистый код. Меня не волнует шанс 1 из миллиона, что что-то может пойти не так и ради этого шанса писать код более грязным.

Можно вообще из дома не выходить, а то вдруг кирпич на голову упадет, если до сих пор не упал, то это просто повезло и проканало из дома выйти да?)

можно зарегистрировать JSX фабрику кастомную

Так и в чём проблема сразу сделать хорошо, а не говнокодить?

Так и в чём проблема сразу сделать хорошо, а не говнокодить?

Если нет разницы, то зачем платить больше?

Вообще-то меньше. Завязываем с демагогией.

Пару замечаний о mobx. Согласен, что mobx это крутое решение для работы с состоянием. У меня мало опыта с разными менеджерами состояний, пробывал redux, и немного overmid, но как только ознакомился с документацией, я понял что работать с состоянием я буду только с mobx.

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

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

Использовать бестпрактисы ООП. Паттерны, SOLID, DI, GRASP, вот это вот всё. Ничего придумывать не надо.

разработчики не понимают когда использовать computed, когда использовать autorun, а когда reaction.

Наверно, те разработчики просто не читали документацию.

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

"Например, если мы захотим хранить ту же историю изменений в каком-нибудь редакторе."

Если вы хотите хранить историю изменений, то тут гораздо лучше подходит Immer от автора Mobx (так как Immer считает diff'ы между стейтами), а не Redux, который будет запоминать N-последних слепков всего стейта. В документации к Redux пишут, что с ним легко делать undo, но на практике это будет отъедать всю память, об этом в том числе писал и сам Абрамов: https://twitter.com/dan_abramov/status/1295823989542211590

Один нюанс, слепки памяти не являются полными при иммутабельности. Общие объекты между изменениями переиспользуются по ссылкам, это называется structural sharing. Так что это сводится к тому же хранению разницы. Возможно иммутабельный подход будет кушать даже меньше памяти при undo/redo, так как все эти proxy и observers на каждое поле тоже едят не мало

Для истории изменений всё так же остаётся концепт трансформеров (теперь уехали в mobx-utils, раньше это лежало в самом mobx), благодаря которому каждый кусок мутабельного стейта mobx можно превращать в иммутабельный, и куда-то складывать. И там уже что душа желает — хоть слепки делать, хоть диффы, хоть еще что угодно.


Ну и не говоря уж про то, что задача "хранить историю изменений" на самом деле нужна совсем уж не часто (гораздо менее часто, чем это пытается показать реклама редакса).

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

Ещё тут надо отметить, что мобиксовый observer не всесилен. Например, есть такой FlatList из react-native. Он получает в пропсы массив и рендерит его со скроллом и прочими плюшками. Внутри себя FlatList просто рендерит VirtualizedList (с передачей массива ему), а тот уже делает цикл по массиву. Навешивать observer на FlatList бесполезно, мутабельные изменения самого массива (например, push) пойманы не будут. Вот он, очень простой кейс, когда вместо push приходится иммутабельно arr = [...arr, newItem]

А в чем тут проблема обернуть FlatList в HOC, в котором запустить reaction() и пропихивать в FlatList новый инстанс массива при каждом его изменении? С помощью reaction всегда можно "выйти" из реактивности mobx в суровый внешний мир и отдавать этому внешнему миру изменения именно в том виде, в котором он желает.

Отступы! Где чертовы отступы??

При этом все они автоматически мемоизируются MobX, что позволяет надеяться на хорошую производительность приложений.

Тут надо помнить, что мемоизация живет, пока есть хотя бы один наблюдатель за компутедом (или указана специальная опция). Если нет, то перевычисляется каждый раз. Так что если это надо именно для производительности, то возможно придется подстраховать через memoize/memoizeOne/etc

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

Если за компутедом никто не наблюдает, то по умолчанию он вообще не вычисляется.

Будет вычисляться при каждом вызове из нереактивного кода. Это я к тому, что computed не на 100% замена memoize.

поэтому возможность создавать хранилища посредством объектов в новой версии считаю отличным выбором

Для этого вам всегда нужно помнить, что же конкретно делает makeAutoObservable. А делает она очень многое, и если в простых случаях там всё легко, то в сложных — сюрпризы очень возможны.
А если вы будете брать makeObservable, то там всегда будет дублирование деклараций (сначала указать поле, а потом еще объяснить mobx, что поле "blahblah" надо оформить как обсервабл).
И только с декораторами всё всегда читается совершенно однозначно и без дублирования. При этом я отлично понимаю, почему в доке mobx появился тезис "мы не рекомендуем использовать декораторы" (потому что со стандартом декораторов происходит тот еще цирк).

Декорирование — древний концепт, и нападок на него как на паттерн я не понимаю. Это оборачивание функции в новую функцию, которая делает что-то дополнительное, а затем вызывает оригинал [+ что-то дополнительное]. Если нападки на синтаксис с "собачкой" над свойствами класса — так это можно воспринимать как сахар, который стабильно корректно транспайлится бабелем уже много лет и не вызывает проблем.


Пожалуй, отказ от этого сахара может быть только по одной более-менее разумной причине — желании сохранять итоговый код как можно ближе по синтаксису к исходному. Но тогда исходный надо писать на ES2015 — на Хабре есть такие любители, даже если профессионалы, но все равно встречаются нечасто. А тут вот в статье еще один — никаких классов (для сторов и для компонентов), никаких типов, никакого Prettier с форматированием с отступами. Удивительно, что Proxy со скрипом, но приняты к использованию...

никаких типов

Только в примерах, так то я активно работаю с JSDoc и/или Typescript.

никакого Prettier с форматированием с отступами

Извините, форматирование есть в исходнике статьи, просто пока не разобрался почему отображается она без них. К Prettier и Eslint я давно привык, и не представляю как без них можно работать.

С приходом 6 версии перестали быть нужны классы и декораторы. И то, и другое я считаю ненужным и даже вредным синтаксическим сахаром

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

Да, я в целом за имутабельность

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

Для референса, моя архитектура имеет схожести с решением в данной статье: https://blog.logrocket.com/using-mobx-for-large-scale-enterprise-state-management/

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

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

Я целый год писал на иммутабельном redux и вообще не понимаю в чем прикол. Что дает иммутабельность в реальном frontend проекте?

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

JavaScript-классы не просто полезны, а необходимы для того, чтобы обеспечить какое-то приближение к изоморфизму с серверным кодом на основных объектно-ориенторованных языках. И борьбы с тошнотой и триггерфингерным рефлексом у серверных разработчиков, которые вынуждены заниматься фронтом :)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории