#1 Redux JS - Вступление

poster
Начинам знакомство с Redux - React библиотекой, которая сейчас у всех на слуху. В этом видео мы разберем что такое Redux JS на простом примере.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

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

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

Мы с вами будем рассматривать его вместе с react, так как они отлично сочетаются. React отвечает только за view слой в приложении, а redux хранение данных и работу с ними.

Но, вместо тысячи слов давайте лучше попробуем написать кусочек кода с использованием redux.

Для начала давайте установим redux в наш проект.

npm install redux --save --save-exact

Закомментируем пока содержимое файла index.js. И импортируем createStore из пакета redux.

import { createStore } from 'redux';

И попробуем создать store приложения.

const store = createStore();

Store - это наше хранилище всех данных в приложении. Любые данные, мы будем хранить в этом обьекте.

Если мы посмотрим в браузер, то увидим ошибку.

createStore.js:69 Uncaught Error: Expected the reducer to be a function.

Это потому, что на вход функции createStore нужно передать функцию, которая будет изменять наш store.

Допустим у нас будет приложение, которое работает с треками и плейлистами.

function playlist(state = []) {
  return state;
}

const store = createStore(playlist);

Мы добавили функцию playlist, которая на вход получает state с дефолтным значением и возвращает его. Как мы видим, в браузере пропали ошибки и мы можем использовать наш store.

И первое, что нас интересует - это как выглядит наш store. Давайте законсолим его.

console.log(store.getState());

И сейчас это у нас пустой массив.

Теперь нас интересует, как нам подписаться на изменение нашего store, чтобы знать, что у нас изменились данные в нем. Очень просто. Для этого у стора есть subscribe метод.

store.subscribe(() => {
  console.log(store.getState());
})

Мы вызываем store.subscribe и передаем в него callback, который выстрелит, если у нас поменяется значение в store. И чтобы видеть, на какое значение оно поменяется, мы консолим store.getState.

Теперь давайте поменяем наше значение в store. В этом нам поможет функция dispatch. Это единственный способ поменять значение в store.

store.dispatch({ type: 'ADD_TRACK', payload: 'Smells like spirit' });

Функция dispatch принимает на вход обьект и единственное, но обязательное - это поле type. Собственно, dispatch - это action, то есть событие, а type - это тип этого события. В данном случае событие добавить трек. В поле payload содержатся данные.

Это еще не все, так как мы выстрелили action, но не отреагировали на него в нашей функции playlist. Давайте законсолим action в этой функции, который идет вторым аргументом.

function playlist(state = [], action) {
  console.log(action);
  return state;
}

Если мы посмотрим в браузер, то мы увидим 2 обьекта. Первый с типом @@redux/INIT, это событие, которые стреляет, когда redux инициализирован. Второй обьект - это как раз наш action. И мы видим в нем наш type и payload.

Давайте теперь добавим код, который будет менять наш стор. Для этого просто поставим условие, если type равняется ADD_TRACK, то добавляем значение в массив.

function playlist(state = [], action) {
  if (action.type === 'ADD_TRACK') {
    return [
      ...state,
      action.payload
    ]
  }
  return state;
}

Как вы видите, я тут использовал оператор spread из es7, чтобы добавить значение в массив и вернуть новый массив. Это очень важно, так как наш стор иммутабельный, и это значит, что мы можем только создавать новую копию данных, а не менять старое состояние store. Это делает работу с данными очень просто и гибкой.

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

store.dispatch({ type: 'ADD_TRACK', payload: 'Enter Sandman' });

В браузере у нас отображается 2 массива, с одной записью и с двумя записями. То есть мы по шагам можем видеть, как меняется store при применении екшенов.

Давайте еще раз пройдем по тому, что мы сделали

  1. Создали новый store для нашего приложения
  2. Передали в него функцию, которая получает екшены и меняет store
  3. Подписались на изменения store с помощью функции subscribe
  4. Выстрелили action с данными
  5. Функция playlist меняет данные с store
  6. Теперь в callback функции subscribe мы всегда знаем, как выглядит наш стор и можем что-то перерисовать на странице.

Но об этом мы поговорим в следующем уроке.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Jin zakk
25 дней назад
недавно на собесе меня спросили: "зачем в редаксе использовать иммутабельный стейт?". Я не дал внятного ответа, тк для меня это было очевидно. Но эту "очевидность" я объяснить не смог. После я быстро погуглил этот вопрос и выделил для себя два ответа: 1) можно быстро понять, изменился ли стейт (тк ссылки на объекты разные) 2) гарантия того, что стейт не был случайно изменен Есть ли еще какие-нибудь преимущества иммутабельного стейта?
monsterlessons
25 дней назад
Отличный вопрос! Но я бы сначала спросил почему иммутабельные данные лучше чем мутабельные: 1. Вы не измените случайно данные (особенно это чревато, если вы передали в функцию обьект и его изменили) 2. Вам проще логать переменные - у вас не будет такого что вы логаете обновленное состояние переменной тк она мутируется позже и в логе вы видите сразу последнее значение 3. Иммутабельный код обычно сложнее писать и проще поддерживать По факту то, что стейт редакса иммутабельный получает стандартные плюсы иммутабельность плюс: 1. Возможность видеть каждый снепшот стейта с помощью devtools 2. Соответственно легкий дебаг тк виден каждый дифф между прошлым и нынешним состоянием 3. Если вы мутируете стейт, то редакс не сможет правильно сравнить состояния тк он делает shallow equal. Если что на оффсайте хорошо все написано: https://redux.js.org/faq/immutable-data#why-is-immutability-required-by-redux
der nohchxa
1 месяц назад назад
Неимоверно кайфовые уроки! Все сразу стало ясно! Это превосходно! Уже дней 10 не могу понять что это за редакс такой, а тут все четко, практично, без воды, и очень круто!
monsterlessons
1 месяц назад назад
Рад, что вам понравилось!
Petr Pozhoga
2 лет назад
Добрый день, правильно понимаю, что как только мы используем Redux то в Reacte нельзя пользоваться локальным стейтом и вся архитектура переносится в Redux в плоть до пагинации (количество страниц, текущая страница и т.д) ?
monsterlessons
2 лет назад
Добрый день. Абсолютно наоборот. Нет никаких норм и стандартов. Используйте то, что вам нравится и когда вы видите в этом смысл. Используя на проекте Redux я стараюсь переносить все состояния кроме форм в Redux, просто по той причине, что дебажить 1 стейт проекта проще чем 2. И не нужно думать "А я тут пишу в локальный стейт или в redux?". Тогда для дебага мне достаточно посмотреть в devtools на экшены, чтобы понять в каком месте баг.
Moe Green
2 лет назад
Приступил к Redux. Мысли такие - поправьте меня, если я неправ. Забавно получается - во Vuex все находится в одном месте - state, mutations, actions. Actions пробрасываются в тот компонент, где они необходимы. В Redux сами actions не находятся в одном месте, а объявляются в том компоненте, в котором будут использоваться. И только потом они пробрасываются "назад", в reducer. Да? )
monsterlessons
2 лет назад
В Vuex все сводится к одному месту, но все можно разбить на отдельные файлы. В Redux actions могут находится где-угодно и использоваться где-угодно. Редьюсер просто слушает все экшены и по type вы можете изменять, что хотите.
Moe Green
2 лет назад
"... но все можно разбить на отдельные файлы." - да, там есть где поизвращаться с разбивкой ) Фактически - action-reducer - это обыкновенный паттерн Pub/Sub?
monsterlessons
2 лет назад
У него односторонний data flow. Этим он и лучше.
Moe Green
2 лет назад
благодарю! )
Moe Green
2 лет назад
И кстати - что вы думаете по поводу MobX? Один из поклонников React мне посоветовал смотреть в сторону MobX вместо Redux.
monsterlessons
2 лет назад
Кому то он нравится больше чем Redux. Я предпочитаю использовать Redux.
Moe Green
2 лет назад
"И первый вопрос конечно ..." - почему редУкс?! Вроде как редАкс должно быть. )) https://egghead.io/courses/getting-started-with-redux
monsterlessons
2 лет назад
Вы правы
Максим Сафаралиев
3 лет назад
Правильно ли я понимаю, что данные из API можно хранить в store? Например выгрузить из JSON список данных. Или такой подход не верный?
monsterlessons
3 лет назад
Этот подход абсолютно верный и именно для этих данных в 90% используется store. Также там можно хранить данные, нужные только на клиенте, данные из локалстораджа и вообще из любого ресурса данных.
Orlik
3 лет назад
Спасибо за качественный контент. У вас талант)
monsterlessons
3 лет назад
Спасибо. Очень приятно. Стараюсь.