Redux и MobX — плюсы и минусы, когда лучше что использовать?
==============================================================

 Недавно в проекте перешли на Redux, все нравится, очень удобно.  

Но вот уже на пороге новый зверь MobX, тоже управляет состоянием приложения.  
  

Кто пользовался, в чем плюсы\недостатки?  

Когда какой инструмент использовать? 

**4 причины использовать MobX**  
1. 1 Легко научиться и использовать
2. Меньше кода писать
3. Полная поддержка объектно-ориентированного программирования
4. Работе с вложенными данными легко

**2 Причины не использовать MobX**  
1. Слишком много свободы
2. Трудно отлаживать

  
  

Я использую MobX сейчас, потому что я могу писать код в 3 раза быстрее, чем с Redux.  
  

Редукс в значительной степени зависит от принципов функционального программирования:  

На мобкс влияет объектно-ориентированное программирование и принципы реактивного программирования: 

 Сразу скажу - **не использовал** MobX, но если вы читаете дальше - значит интересуетесь.   

Ответ про плюсы redux для меня лично - в самом конце.  

---  

До React, писал на angular, и еще раньше на backbone. В ангуляр разработке у меня были места, которые я для себя объяснял: ок, так работает ангуляр (дайджест там, скоуп такой хитрый и т.д.) - факт был в том, что не все было прозрачно для меня лично.  
  

Начал разбираться с React и переписал часть рабочего проекта на React + Flux. В целом понравилось, но немного напрягало копирование однотипного кода. Появился redux, который (это важно) решил мою проблему. **Все**, тут я сделал остановку. Написал еще пару внутренних проектов - понравилось. Меня не напрягает ничего. Все уместно, код читается хорошо. Если я возвращаюсь к старому проекту - я очень быстро вникаю в "как это работает" и могу приступить к решению задачи.  
  

В процессе работы с Redux - появился Graph QL. Клево! Опять что-то новенькое - начал разбираться, и закрыл - так как быстро въехать не получилось, и попутно мне пришла простая мысль: зачем? Меня устраивает то, как работает связка React + Redux. Поэтому, я не стал вникать в saga, и пока что не хочется вникать в MobX. Возможно, это не правильно, ведь я их даже не смотрел, но свободное время от "вникания в новую технологию" я потратил на "дебри" технологий, которые активно использую.  
  

Поэтому, для себя я решил - в ближайшее время сидеть ровно на стуле, не скакать по технологиям и спокойно делать одно приложение за другим. До тех пор пока **не появится какое-то недовольство** текущим стэком.  
  

Главные **плюсы** redux для меня:   

+ Если не трогал проект больше месяца - очень легко вспомнить что к чему.  

+ Я пишу код. Я не вникаю в новое, я наращиваю знания по "старому" => я пишу быстро  

+ Удобно тестировать  
  
**Когда использовать**:   

- когда хотите сделать одностраничное (SPA) приложение с нуля  

- когда хотите постепенно перевести старый проект на схему: вьюха (вся страница, или какой-то блок) + API запросы 

 1) Mobx лучше использовать когда вы не хотите использовать монструозные конструкуции чтобы обновить какой-то объект который находится где-то глубоко внутри дерева состояния, например когда вам нужно обновить комментарий который находится внутри массива комментария объекта "задачи", которая находится внутри массива задач объекта "проекта" (схема примерно такая   

```
store = {
   projects: [
    ... , 
   {id: 'project1', tasks: [
       ... , 
       {id: 'task1', comments: [
           {id: 'comment1', text: 'some text'}
       ]} 
   ]}
]}
```
  

 и где-то в компоненте комментария получив через пропсы объект {id: 'comment10', text: 'some text'} в обработчике ввода текста с mobx-ом вам достаточно будет обновить только одно свойство - comment.text = e.target.value, когда же с redux вам нужно создавать отдельный редюсер и там писать конструкцию которая сначала создаст новый объект коментария потом скопирует старые свойства и дальше запишет при этом свойство text с новым текстом, дальше создает объект задачи и также скопирует его свойства и создаст при этом новый объект массива комментариев и скопирует все комментарии которые были плюс наш новый объект комментария, и дальше все это нужно повторить с проектом и задачами и так с каждым родителем пока не доберемся до верхушки дерева состояния. Есть правда spread-оператор который облегчает этот процесс копирования свойств и элементов массива но конструкции все равно получаются монструозные и чем глубже объект тем они больше.  
  

2) Mobx лучше использовать когда вы хотите чтобы какие-то объекты ссылались друг на друга. Например хотим создать todo-приложение но чтобы там можно было создавать подзадачи к задаче и подзадачи к подзадачам в общем чтобы получилось некое дерево подзадач. Со стороны реакта будет один компонент который рекурсивно будет вызвать себя для всех подзадач.  

```
const Task = ({task})=> (
  <div>{task.children.map(subtask=><Task task={subtask}>)}</div>
  )
```
  

И теперь допустим вы решили ограничить количество подзадач к одной задачи. И хочется в обработчике написать примерно такое условие - if(this.props.task.parent.children.length > 10) return; то есть попросту говоря обратиться к объекту родительской задаче через свойство .parent. C mobx это возможно прямо как в этом примере а вот c redux это невозможно (потому что из-за того что объекты ссылаются друг на друга и необходимость возвращать новый объект состояния вызовет рекурсивное пересоздание всех объектов) и там для написания древовидных интерфейсов нужно делать нормализацию стора и передавать айдишник и писать еще кучу лишнего кода. И при этом не получится в обработчике обратится к объекту родителя так как this.props.task.parent будет айдишником и значит нам еще нужно обращаться к стору чтобы вытащить объект по его айдишнику (например через thunk - dispatch((\_, getState)=>getState().tasks[this.props.task.parent]).children.length. А если нужно обратится к еще более родительской задачи - то нужно уже два раза вытаскивать объект из стора по его айдишнику. А в случае когда у нас большое приложение где у юзер может создавать папки, у папках проекты, у проектах задачи, у задачи комментарии то чтобы в компоненте комментария обратится к папке в котором находится комментарий c mobx достаточно просто написать comment.task.project.folder.name а вот с redux-ом будет примерно такая неудобная конструкция state.projects[state.projects[state.tasks[comment.taskId].projectId].folderId].name и в больших приложениях код бизнес-логики будет постоянно перемазан вот таким вот кодом вытаскивания объекта из стора по его айдишнику на каждый чих 

 Дело в том, что Redux позиционируют, как законченную CQRS + ES архитектуру для разработки в функциональном для frontend программистов. Backend программисты, привыкли к более традиционной архитектуре в ооп стиле, к которой и обязывает mobx. То есть mobx является vm (view-model) из mvvm.  
  

Выходит что предпочтение к архитектуре и парадигме является первым указателем для выбора той или иной библиотеки.  
  

Второй указатель появляется тогда, когда Вы начинаете работать с большим количеством данных и Вам не нужна CQRS архитектура. При таких условия Redux начинает отпугивать за счет иммутабельности, а Mobx притягивать за счет мутабельности данных.  
  

И лично я считаю что на этом все. Единственное могу добавить, что с Redux можно добиться желаемого ровно так же, как и с Mobx все испортить. Я писал и на том и на другом и знаю не по наслышке, что все не так как говорят, везде есть свои нюансы.