Примечание 2019 г.: вам совершенно не нужно использовать redux. Это может быть вам полезно, а может и нет. Самое главное - правильно рассуждать о состоянии. Вы сохраняете состояние локальным там, где это имеет смысл, повышаете его, когда это необходимо, и создаете компонуемые приложения. Какая библиотека вы используете для этого (если вы решите использовать ее вообще - чего я больше не использую), является второстепенной по сравнению с тем, как вы структурируете свое состояние.

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

Например, скажем, вы пишете блог. Вам не нужны комментарии (если я хочу такого рода оскорбления, я просто получу в Твиттере) - только необработанный текст, изображения и заголовки. Довольно просто. Для этого нам не нужен поток. Для этого нам, вероятно, даже не нужен React.

Но я? Я разработчик, а это значит, что я не понимаю, насколько сложна проблема, пока не закончу пачку Redbull и не заполню доску. В этот момент я наклоняюсь к своему другу и говорю: «Ага, я думаю, это нетривиально.

Как вы думаете, есть ли шанс, что ваше приложение вырастет до такой степени, что вам понадобится сокращение? Если так, не ждите - сделайте это прямо сейчас.

Почему?

Redux меняет ваши представления о состоянии *

Я не могу выразить, насколько это было правдой для меня. Например, я представлю, что мы пишем текстовый редактор. (Кстати, можем мы на мгновение согласиться с тем, что написание собственного текстового редактора для вашего проекта - ужасная идея? Поверьте мне, в этом вопросе… Я не думаю, что у меня есть место, чтобы вдаваться в подробности).

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

Документ:

{
  sections: []
}

Раздел:

{
  id: 1,
  type: 'text',
  title: 'Heading',
  selectedLine: 1,
  lines: []
}

Линия:

{
  id: 1,
  type: 'text',
  content: 'The assyrian came down like a wolf on the fold'
}

Три отдельных компонента, каждый из которых контролирует свои собственные состояния. Все это имеет смысл на первый взгляд (игнорируя сложность, унаследованную от проблемного пространства). Например, если бы я хотел изменить текст в строке, мне нужно было бы управлять только содержимым этого Line компонента. Секции не нужно было бы знать о состоянии линии. Точно так же секция будет заботиться только о строках, которые у нее есть, но не о том, что в строках. Мы могли перемещать строку в разделе или между разделами, не зная содержимого.

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

// Section component that owns state
deleteLine = (id, content) => {
  const lines = [ ...this.state.lines]
  const index = this.state.lines.findIndex(line => line.id === id);
  const lineToUpdate = Object.assign(this.state.lines[index - 1], {});
  // wait how do I tell it to update? refs? some prop?
  lineToUpdate.someProp = content;
  lines[index - 1] = lineToUpdate;
  // uh maybe this is wrong.

Итак, вы видите здесь сложность? Все потому, что мы думали о своем состоянии «разумно». Но когда мы переходим к redux, весь наш документ находится в нашем хранилище, и ни один компонент не будет контролировать свое собственное состояние. Итак, эта проблема, на решение которой мы потратили час (ладно, может быть, я потратил больше), в конечном итоге оказалась тривиальной. Мы просто отправляем такое действие, как:

// DocumentActions.js
const DeleteLine = (sectionId, lineId, content) => {
  return({ type: 'DELETE', sectionId, lineId, content });
}
// DocumentReducer.js
case 'DELETE':
  const section = state.document.sections[sectionId];
  const lineToDelete = section.lines[lineId];
  const index = section.lines.findIndex(id => id === lineId);
  // now we know what we need to know. We can account for it being
  // the first line in the section. Or the first line in the  
  // document. We have all the information.

Итак, на решение этой проблемы мы потратили столько времени? Это совсем не та проблема, которую нам нужно решать. Мы потратили время и познавательное пространство на решение, которого в итоге не нашло с помощью redux. Это еще называют потерей времени :)

* Теперь я понимаю, что, возможно, более точным заголовком для моего заголовка могло бы быть «Это меняет наши представления о изменении состояния».

Redux меняет ваши представления о компонентах

Это довольно просто. Когда вы выводите состояние из компонентов, это заставляет вас задаться вопросом, действительно ли им нужно вообще расширять Component. Может быть, они могут быть просто чисто функциональными составляющими? Например, заголовок с текстовым вводом для поиска по содержимому нашего текущего экрана - мы могли бы считать это частью самого компонента до redux. Я имею в виду, что это изменение списка в нашем состоянии, верно?

class SomeComponent extends Component {
state = {
  list: []
}
filterList = () => { ...modify the results }
render() {
  return (
    <View>
      <TextInput onChangeText={this.filterList}></TextInput> 
      ...rest of the component
    </View>
  );
}

Но когда мы переходим на redux, мы можем фильтровать наш список через магазин, если захотим. Это означает, что мы могли бы переместить наш компонент заголовка в какой-нибудь другой файл, где он принимает метод фильтрации в качестве опоры. По моему опыту, это разложение имеет эффект снежного кома. Как только вы удалите один набор методов и рендеринга, вы начнете понимать, что другие «неотъемлемые» части компонента оказываются собственными небольшими повторно используемыми секциями. TextInput, который фильтрует результаты в одной части вашего приложения, может фактически фильтровать любой список в вашем приложении.

Многое из этого более тривиально, чем рассуждения о состоянии. Вы не тратите так много времени на перемещение вещей, но вы все равно пересматриваете свои решения, принятые ранее, когда компоненты переходят на сокращение. Вы пропускаете это «переосмысление», если раньше изменили свое приложение. Хотя я фанат переписывания и частого переписывания, все же нужно двигаться в правильном направлении. Redux объединяет идеи, которые вы раньше не считали связанными. (поняли, ребята? connect?)

Переключение болезненное

Это довольно просто. Это причина, по которой вы вообще не хотите использовать сокращение. Я действительно согласен с вами. Если вы никогда не использовали его раньше, redux - это сложно. Изучать его, как и многие другие вещи, мучительно. Вы ошибаетесь, и вам нужно переписать, но тогда вы снова ошибаетесь. Это другой образ мышления.

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

Прыжок того стоит.

Вы знаете, что хотите правильно? Просто пойти на это.