Содержание

Redex

Приветствую вас! Посмотрите, как заработать с компанией REDEX!!!

Что такое REDEX:

— Справедливый маркетинг. У нас НЕТ реферальных – В СЕТЬ ИДЕТ 100%!

— Компания REDEX — работает на криптовалюте BITCOIN

— Свой биткоин-кошелек RDXcoin

— При регистрации автоматически создается внутренний кошелёк

— Моментальный вывод денег, в любое время. Автоматический реинвест.

— Никаких ежемесячных абонентских плат за пользование системой.

— МИНИМАЛЬНЫЙ ВХОД

Компания зарегистрирована в Лондоне. СЕРТИФИКАТ для деятельности. SSL сертификат для защиты от хакеров или любого, кто хочет украсть информацию! 

Официальные документы компании:

Проверить здесь:

https://vk.com/doc-64487434_437380847?dl=3680465b1bcb..

                                                             

                                           Стратегия заработка 

   Наша команда работает по стратегии «Золотой треугольник».

Маркетинг

Результат работы партнера компании Redex

5500$ за 9 дней

Инструкция

REDEX лохотрон? Не дождетесь!

Вернемся к приложению Counter, давайте на секунду представим, что мы переместили состояние компонента в Redux.

Мы удалим состояние из компонента, так как скоро мы получим его от Redux:

  импортировать React из react;

class Counter расширяет React.Component {
  инкремент = () => {
    // заполним позже
  }

  декремент = () => {
    // заполним позже
  }

  render () {
    возвращение (
      

Счетчик

{this.props.count}
) } } экспорт счетчика по умолчанию;

Подключение счетчика

Обратите внимание, что {this.state.count} изменилось на {this.props.count} . Конечно, это пока не сработает, потому что счетчик не получает опору count . Мы собираемся использовать Redux, чтобы внедрить это.

Чтобы получить подсчет Redux, нам сначала нужно импортировать функцию connect вверху:

  импорт из 'react-redux';  

Затем нам нужно «подключить» компонент Counter к Redux внизу:

  // Добавьте эту функцию:
function mapStateToProps (состояние) {
  возвращение {
    count: state.count
  };
}

// Затем замените это:
// экспорт по умолчанию Counter;

// С этим:
экспортировать соединение по умолчанию (mapStateToProps) (Counter);  

Это завершится ошибкой (подробнее об этом через секунду).

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

Что такое подключить ?

Вы могли заметить, что звонок выглядит немного… странно. Почему connect (mapStateToProps) (Counter) , а не connect (mapStateToProps, Counter) или connect (Counter, mapStateToProps) ? Что это делает?

Это написано так, потому что connect - это функция высшего порядка , что является причудливым способом сказать, что она возвращает функцию, когда вы ее вызываете.А затем вызов , что функция с компонентом возвращает новый (завернутый) компонент.

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

Что делает connect , так это подключается к Redux, извлекает все состояние и передает его через предоставляемую вами функцию mapStateToProps . Это должна быть настраиваемая функция, потому что только вы, , будете знать «форму» состояния в Redux.

connect передает все состояние, как бы говоря: «Эй, скажите мне, что вам нужно из этого беспорядочного беспорядка».

Объект, который вы возвращаете из mapStateToProps , передается в ваш компонент в качестве свойств. В приведенном выше примере будет передано значение state.count как значение свойства count : ключи в объекте становятся именами свойств, а соответствующие им значения становятся значениями свойств. Итак, вы видите, что эта функция буквально определяет отображение состояния в свойства .

Ошибки - это прогресс!

Если вы следите за инструкциями, в консоли вы увидите сообщение об ошибке:

Не удалось найти «store» ни в контексте, ни в свойствах «Connect (Counter)». Либо оберните корневой компонент в a, либо явно передайте «store» в качестве опоры для «Connect (Counter)».

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

Предоставить магазин

Redux содержит глобальное состояние для всего приложения, и, обернув все приложение компонентом Provider из react-redux , , каждый компонент в дереве приложений сможет использовать connect для доступа к Redux. хранить, если захочет.

Это означает App и дочерние элементы App (например, Counter ), а также дочерние элементы своих дочерних элементов и т. Д. - все они теперь могут получить доступ к хранилищу Redux, но только если они явно обертываются вызовом к подключите .

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

Этот Provider сейчас может показаться абсолютной магией. Это немного; он фактически использует «контекстную» функцию React.

Это похоже на секретный проход, соединенный с каждым компонентом, и с помощью connect открывает дверь в проход.

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

В src / index.js импортируйте поставщик Provider и оберните им содержимое App .

  импорт {Provider} из 'react-redux';

...

const App = () => (
  <Провайдер>
    <Счетчик />
  
);  

Мы все еще получаем эту ошибку - это потому, что Provider нуждается в магазине для работы. Магазин будет использоваться в качестве опоры, но сначала нам нужно создать его.

Создать магазин

Redux поставляется с удобной функцией, которая создает магазины, и называется она createStore . Ага. Создадим магазин и передадим его Провайдеру:

  импорт {createStore} из "redux";

const store = createStore ();

const App = () => (
  
    <Счетчик />
  
);  

Другая ошибка, но на этот раз другая:

Ожидалось, что редуктор будет функцией.

Итак, вот что касается Redux: он не очень умный. Вы можете ожидать, что, создав магазин, он даст вам хорошее значение по умолчанию для состояния внутри этого магазина. Может быть, пустой объект?

Но нет: Redux делает ноль предположений о форме вашего состояния. Тебе решать! Это может быть объект, число, строка или что угодно. Итак, мы должны предоставить функцию, которая будет возвращать состояние. Эта функция называется редуктором (мы поймем, почему через минуту).Итак, давайте сделаем самый простой из возможных, передадим его в createStore и посмотрим, что получится:

  function reducer () {
  // пока оставим это поле пустым
  // что то же самое, что и `return undefined;`
}

const store = createStore (редуктор);  

Редуктор должен всегда что-то возвращать

Ошибка теперь другая:

Невозможно прочитать свойство «count» из неопределенного

Ошибка, потому что мы пытаемся получить доступ к состоянию .count , но состояние не определено. Redux ожидал, что наша функция редуктора вернет значение для состояния , за исключением того, что она (неявно) вернула undefined . Все по праву сломано.

Ожидается, что редуктор вернет состояние. На самом деле предполагается, что он принимает текущее состояние и возвращает новое состояние , но это не важно; мы вернемся к этому.

Давайте заставим редуктор возвращать что-то, что соответствует нужной нам форме: объект со свойством count .

  function reducer () {
  возвращение {
    количество: 42
  };
}  

Эй! Оно работает! Счетчик теперь отображается как «42». Потрясающие.

Только одно: счет навсегда застрял на 42.

История до сих пор

Прежде чем мы перейдем к тому, как на самом деле обновить счетчик , давайте посмотрим, что мы сделали к настоящему моменту:

  • Мы написали функцию mapStateToProps , которая выполняет то, что написано в названии: преобразует состояние Redux в объект, содержащий свойства.
  • Мы подключили хранилище Redux к нашему компоненту Counter с помощью функции connect из react-redux , используя функцию mapStateToProps для настройки того, как работает соединение.
  • Мы создали функцию редуктора , чтобы сообщить Redux, как должно выглядеть наше состояние.
  • Мы использовали гениально названную функцию createStore для создания магазина и передали ей редуктор .
  • Мы обернули все наше приложение в компонент Provider , который поставляется с react-redux , и передали его нашему магазину в качестве опоры.
  • Приложение работает безотказно, за исключением того, что счетчик застрял на 42.

У меня пока?

Интерактивность (заставить его работать)

Я знаю, что пока это довольно неубедительно. Вы могли бы написать статическую HTML-страницу с номером «42» и двумя неработающими кнопками за 60 секунд, но вот вы читаете, как чрезмерно усложнить то же самое с помощью React и Redux, и неизвестно чем еще.

Я обещаю, что в следующем разделе все это окупится.

Собственно, нет. Я беру это обратно. Простое приложение Counter - отличный обучающий инструмент, но Redux абсолютно лишен чего-то вроде этого. Состояние реакции - отлично, для чего-то такого простого. Черт возьми, даже простой JS будет отлично работать. Выберите подходящий инструмент для работы. Redux не всегда такой инструмент. Но я отвлекся.

Исходное состояние

Итак, нам нужен способ сообщить Redux об изменении счетчика.

Помните функцию редуктора , которую мы написали? (конечно, это было 2 минуты назад)

Помните, как я упоминал, что он берет текущее состояние и возвращает новое состояние ? Что ж, я снова солгал.Фактически он принимает текущее состояние и действие , а затем возвращает новое состояние. Надо было написать так:

  редуктор функции (состояние, действие) {
  возвращение {
    количество: 42
  };
}  

В самый первый раз, когда Redux вызывает эту функцию, он передает undefined как состояние . Это ваша реплика, чтобы вернуть начальное состояние . Для нас это, вероятно, объект с числом , равным 0.

Обычно начальное состояние пишется над редуктором и используется функция аргумента ES6 по умолчанию, чтобы предоставить значение для аргумента состояния , когда он не определен.

  const initialState = {
  количество: 0
};

редуктор функции (состояние = начальное состояние, действие) {
  вернуть состояние;
}  

Попробуй. Он все еще должен работать, за исключением того, что теперь счетчик застрял на 0 вместо 42. Отлично.

Действие

Наконец-то мы готовы поговорить о параметре action . Что это такое? Откуда это взялось? Как мы можем использовать его, чтобы изменить чертов счетчик?

«Действие» - это объект JS, который описывает изменение, которое мы хотим внести.Единственное требование - объект должен иметь свойство типа , а его значение должно быть строкой. Вот пример действия:

Вот еще один:

В твоей голове крутятся шестерни? Ты знаешь, что мы будем делать дальше?

Ответить на действия

Помните, что задача редуктора - взять текущее состояние и действие и вычислить новое состояние. Итак, если редуктор получил действие типа {type: "INCREMENT"} , что вы можете вернуть в качестве нового состояния?

Если вы ответили примерно так, вы на правильном пути:

  функция-редуктор (состояние = начальное состояние, действие) {
  если (действие.type === "INCREMENT") {
    возвращение {
      count: state.count + 1
    };
  }

  вернуть состояние;
}  

Обычно используется оператор switch с case s для каждого действия, которое вы хотите обработать. Измените редуктор, чтобы он выглядел так:

  функция-редуктор (состояние = начальное состояние, действие) {
  switch (action.type) {
    case 'INCREMENT':
      возвращение {
        count: state.count + 1
      };
    дело «ЗАПРОС»:
      возвращение {
        count: state.count - 1
      };
    по умолчанию:
      вернуть состояние;
  }
}  
Всегда возвращать состояние

Вы заметите, что всегда есть резервный вариант , когда все, что он делает, это , возвращает состояние .Это важно, потому что Redux может (будет) вызывать ваш редуктор с действиями, с которыми он не знает, что делать. Фактически, самое первое действие, которое вы получите, - это {type: "@@ redux / INIT"} . Попробуйте поместить console.log (действие) над переключателем и посмотрите.

Помните, что задача редуктора - вернуть новое состояние , даже если это состояние не отличается от текущего. Вы же никогда не хотите переходить от «наличия состояния» к «state = undefined», верно? Вот что произойдет, если вы откажетесь от случая по умолчанию .Не делай этого.

Никогда не менять состояние

Еще одна вещь, которую нельзя делать: не изменяйте в состояние . Состояние непреложно. Вы никогда не должны его менять. Это означает, что вы не можете этого сделать:

  function brokenReducer (state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      // НЕТ! ПЛОХО: это меняющееся состояние!
      state.count ++;
      вернуть состояние;

    дело «ЗАПРОС»:
      // НЕТ! ПЛОХО: это тоже меняющееся состояние!
      штат.count--;
      вернуть состояние;

    по умолчанию:
      // это отлично.
      вернуть состояние;
  }
}  

Вы также не можете делать такие вещи, как state.foo = 7 или state.items.push (newItem) или delete state.something .

Думайте об этом как об игре, в которой единственное, что вы можете сделать, это вернуть {...} . Это забавная игра. Сначала сводит с ума. Но со временем вы научитесь лучше.

Я собрал краткое руководство о том, как делать неизменяемые обновления, показывая 7 общих шаблонов для обновления состояния в объектах и ​​массивах.

Все эти правила…

Всегда возвращайте состояние, никогда не меняйте состояние, не подключайте все компоненты, ешьте брокколи, не уходите после 11… это утомительно. Это похоже на фабрику правил, и я даже не знаю, что это такое.

Да, Redux может быть как властный родитель. Но это исходит из любви. Функциональное программирование люблю.

Redux построен на идее неизменности, потому что изменение глобального состояния - это путь к гибели.

Вы когда-нибудь сохраняли глобальный объект и использовали его для передачи состояния приложению? Поначалу он отлично работает.Легко и приятно. А потом состояние начинает непредсказуемо меняться, и становится невозможным найти код, который его изменяет.

Redux позволяет избежать этих проблем с помощью некоторых простых правил. Состояние доступно только для чтения, и действия - единственный способ его изменить. Изменения происходят в одну сторону, и только в одну сторону: действие -> редуктор -> новое состояние. Функция редуктора должна быть «чистой» - она ​​не может изменять свои аргументы.

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

Откуда берутся действия?

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

Действия не рождаются, но они - это отправлено , с удобной функцией под названием отправка .

Функция отправки предоставляется экземпляром магазина Redux.Иными словами, вы не можете просто импортировать и продолжать свой путь. Вы можете позвонить по номеру store.dispatch (someAction) , но это не очень удобно, поскольку экземпляр store доступен только в одном файле.

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

Вот последний компонент во всей красе. Если вы следовали, то изменились только реализации приращения и приращения : теперь они вызывают опору dispatch , передавая ей действие.

  импортировать React из react;
import {connect} из 'react-redux';

class Counter расширяет React.Component {
  инкремент = () => {
    этот.props.dispatch ({тип: 'ПРИЛОЖЕНИЕ'});
  }

  декремент = () => {
    this.props.dispatch ({тип: 'ЗАЯВЛЕНИЕ'});
  }

  render () {
    возвращение (
      

Счетчик

{this.props.count}
) } } function mapStateToProps (состояние) { возвращение { количество: состояние.считать }; } экспортировать соединение по умолчанию (mapStateToProps) (Counter);

Код всего проекта (всех двух его файлов) можно найти на Github.

Что теперь?

Имея за плечами приложение Counter, вы хорошо подготовлены, чтобы узнать больше о Redux.

«Что ?! Есть больше?!"

Есть много всего, что я здесь не рассмотрел, надеясь сделать это руководство легко усваиваемым: константы действий, средства создания действий, промежуточное ПО, преобразователи и асинхронные вызовы, селекторы и т. Д.Там много. Документация Redux хорошо написана и охватывает все это и многое другое.

Но теперь основная идея у вас есть. Надеюсь, вы понимаете, как потоки данных в Redux ( dispatch (action) -> reducer -> new state -> re-render ), и что делает редуктор, что такое действие и как все это сочетается друг с другом.

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

Успех! Теперь проверьте свою электронную почту.

Изучение React может быть проблемой - столько библиотек и инструментов!
Мой совет? Игнорируйте их всех 🙂
Чтобы получить пошаговый подход, посетите мой семинар по Pure React.

Научитесь думать на React

  • 90+ уроков со скринкастами
  • Полная стенограмма и скрытые субтитры
  • Весь код с уроков
  • Интервью с разработчиками

Начните изучать Pure React прямо сейчас

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

Алан Лаванда

@lavenderlens

Что такое redux и какую проблему он решает?

Переполнение стека

  1. Около
  2. Товары

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

Введение в Redex с абстрагированием абстрактных машин (v0.6)

6.90.0.26

Введение в Redex с абстрактными абстрактными машинами (v0.6)

Дэвид Ван Хорн

Последнее обновление: воскресенье, 15 апреля 2018 г.

1 Введение

Это «живой» артефакт: отправляйте отчеты об ошибках
и запросы на вытягивание всякий раз, когда вы обнаруживаете проблемы в этом документе.
https://github.com/dvanhorn/redex-aam-tutorial/

Эта статья представляет собой краткое введение в программирование Redex.
язык семантического моделирования.Это достигается путем разработки нескольких
семантические модели простого языка программирования, а затем показать, как
построить программный анализатор для этого языка с помощью
Метод «абстрагирования абстрактных машин» (Ван Хорн и Май 2010).

Итак, это руководство направлено на достижение двух целей:

  • (1) знакомство с семантическими инженерами (язык программирования
    исследователи, разработчики и разработчики языков, анализ и инструмент
    строители и др.) на язык программирования Redex;

  • (2) для демонстрации метода построения абстрактных интерпретаторов
    известный как AAM.

Вы можете прочитать это руководство для любой цели. Если ты хочешь учиться
Redex, в этом руководстве будет построено несколько стандартных семантических систем:
редукционные отношения, типовые суждения, оценщики, машины и, наконец,
программный анализатор. Если вы хотите ясного и доступного
введение в метод AAM, это руководство проведет вас через
детальная конструкция.

1.1 Что такое Redex?

Redex (Felleisen et al. 2009) - это язык сценариев и набор связанных инструментов, поддерживающих
концепция, проектирование, построение и тестирование семантических систем
такие как языки программирования, системы типов, логика программ и
программный анализ.Как язык сценариев, он позволяет инженеру
создавать исполняемые спецификации общих семантических элементов, таких как
грамматики, редукционные отношения, суждения и метафункции; базовый
элементы формальных систем. Включает в себя ряд программного обеспечения
Инженерные функции, делающие модели надежными, и включает инструменты
для набора моделей и создания алгебраических степперов для изучения
поведение программы. Короче говоря, Redex поддерживает все этапы
Жизненный цикл семантической инженерии.

Для отличной беседы, мотивирующей Redex, см. Видео
Робби Финдлера
Бегать
Ваш доклад об исследованиях на POPL 2012 (Klein et al.2012).

Я использовал Redex с момента его первого выпуска, и он сыграл очень важную роль.
роль в нескольких моих исследовательских проектах. Это позволило мне быстро
исследовать новые идеи, выдвигать гипотезы и - обычно - опровергать их
претензий и уточняйте идеи. В некоторых случаях Redex облегчил
развитие исследований; Я могу перейти от идеи к результату намного быстрее и
эффективнее, чем я мог бы без Redex. В остальных случаях использование
Redex выявил проблемы, о существовании которых я не знал, что привело к появлению новых
результаты и исследования.Но в других случаях я просто не мог
выполнили свое исследование без Redex.

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

1.2 Что такое абстрагирование абстрактных машин?

Абстрагирование абстрактных машин (сокращенно AAM) - это метод для
систематическое построение анализаторов звуковых программ. Центральная идея
состоит в том, что семантика языка программирования может быть преобразована с помощью
простая конструкция с поворотной рукояткой, в анализ для надежной
рассуждения о программах, написанных на этом языке.Это было использовано
для анализа ряда языковых особенностей, которые часто рассматриваются за пределами
ряд существующих подходов к анализу. Ключевое преимущество подхода
в том, что идеи разработки и реализации языка программирования могут
быть напрямую импортированным и примененным к разработке и реализации
абстрактные интерпретаторы.

1.3 Предварительные требования

В этом руководстве предполагается, что у вас есть некоторый опыт программирования.
языковые семантические артефакты, такие как грамма

Практическое руководство по Redux

Что такое Redux? ###

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

Этот пост посвящен использованию Redux в приложении React.

Этот пост состоит из трех частей:

  1. Подставка
  2. Элементы Redux (основная часть этого поста)
  3. Пример приложения (очаровательное, э-э, я имею в виду супер-крутое 💪, приложение для создания списка самых разыскиваемых лиц)
Клонировать репо.

Ознакомьтесь с демонстрацией.

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

create-react-app <имя-проекта>

После завершения настройки create-response-app, cd в папку и:

npm install - сохранить redux response-redux axios .

Axios не имеет ничего общего с Redux, но это библиотека, используемая для вызовов AJAX в демонстрационном приложении.

(Если у вас не установлено приложение create-react-app , сначала запустите npm install -g create-response-app .)

Какую проблему решает Redux? ###

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

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

С Redux любой компонент может быть напрямую подключен к состоянию. ####

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

Не рекомендуется, чтобы все компоненты были подключены к состоянию приложения. Лучше всего, чтобы родительские компоненты / компоненты контейнера подключались к состоянию, а передавали состояние напрямую дочерним элементам .

Терминология: Компоненты, подключенные к состоянию, обычно называются «контейнер», или «интеллектуальные» компоненты , и они обычно также выполняют логику. Компоненты, которые не имеют собственного состояния и получают состояние от контейнера компонентов, называются «немыми» компонентами. Иногда эти глупые компоненты представляют собой функциональных и компонентов. В демонстрационном приложении реализованы как компоненты контейнера, так и функциональные компоненты. ( NewUserFace.js и Toast.js являются функциональными компонентами.)

I. Подкладка ###

Вот файловая структура демонстрационного приложения:

  ____________
> обозначает папку
- указывает на файл
____________

> DEMO_APP_FOLDER
  > node_modules
  > общественные
  > src
    > действия
       --action_one.js
       --action_two.js
       --types.js
    > компоненты
    > редукторы
       --reducer_one.js
       --reducer_two.js
       --index.js
    --индекс.js
  

Все папки содержат файлы, но пока нас интересуют только действия и редукторы.

Чтобы включить Redux в проект, к двум файлам необходимо добавить два важных элемента шаблона; основной файл редуктора (строка 15) и основной файл приложения (строка 16).

Файл index.js в строке 16 - это место, где находится основная конфигурация.

  импортировать React из react;
import {render} from 'r  

React Redux Tutorial for Beginners: The Complete Guide (2020)

Самый простой учебник по React Redux, который я хотел бы иметь, когда начал учиться.Включает Redux Toolkit!

Когда я только начал изучать Redux, мне хотелось иметь "Redux для чайников". Я чувствовал себя тупым, потому что не мог осмыслить действия, создатели действий, редукторы . Как насчет промежуточного программного обеспечения? Ты меня разыгрываешь!

Итак, в те дни я начал преподавать Redux, чтобы узнать больше, одновременно с написанием собственного учебника по React Redux. С тех пор я многому научился, и это руководство по React Redux - попытка помочь вам изучить Redux самым простым способом .

Этот учебник также включает Redux Toolkit .

Psst .. Cerchi un tutorial Redux in italiano?

Прочтите это: Redux, где мы сейчас?

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

Однако фундаментальными строительными блоками Redux по-прежнему являются действия , редукторы, промежуточное программное обеспечение и магазин , и вам нужно хорошее знание этих блоков lego, чтобы хорошо владеть Redux и Redux toolkit .

В этом руководстве я сначала расскажу о «классическом» коде Redux, а также о React / Redux с и подключении . Позже вы увидите, как выполнить рефакторинг до Redux Toolkit . Если вы предпочитаете смотреть видео, то посмотрите , этот мой бесплатный курс Redux .

А теперь наслаждайтесь чтением!

СОДЕРЖАНИЕ

Руководство по

React Redux: для кого это руководство для

Следующее руководство по React Redux предназначено для разработчиков JavaScript, хорошо разбирающихся в ES6 и React .В Интернете есть бесчисленное количество руководств по React, если вы хотите освежить свое понимание, но если вы только начинаете, я предлагаю прочитать «Начало работы с React» Тани Расция.

Учебник по

React Redux: что вы узнаете

Руководство охватывает в основном Redux с React из-за широкого распространения этой комбинации, но Redux также может использоваться как автономная библиотека без какой-либо внешней оболочки / библиотеки.

Итак, из следующего руководства вы узнаете:

  • что такое Redux
  • Строительные блоки Redux
  • как использовать Redux автономный
  • как использовать Redux с React

Руководство по React Redux: минимальная среда разработки React

Перед тем, как начать, убедитесь, что у вас установлена ​​среда разработки React . .

Чтобы сделать его, вы можете следовать инструкциям по настройке React, webpack и Babel или, что еще лучше, использовать create-response-app:

  npx create-react-app react-redux-tutorial  

Как только закончите, можно идти.

Учебник по

React Redux: в каком состоянии?

Что такое Redux ? Чтобы ответить на этот вопрос, мы должны сначала поговорить о состоянии в веб-приложениях JavaScript . Рассмотрим простой пользовательский поток:

«как пользователь я могу щелкнуть кнопку с именем« Нажми меня, и модальное окно должно появиться вскоре после этого ».

Угадайте, что, даже в этом тривиальном взаимодействии есть состояние , с которым мы должны иметь дело. Например, мы можем описать начальное состояние приложения как простой объект JavaScript:

  const state = {
  buttonClicked: 'нет',
  modalOpen: 'нет'
}  

Когда пользователь нажимает, состояние меняется, и мы имеем:

  const state = {
  buttonClicked: 'да',
  modalOpen: 'да'
}  

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

Также, если вы работали с React до того, как термин «состояние» вас не удивит.Думаю, вы уже написали какой-то компонент React с отслеживанием состояния, например:

  импортировать React, {компонент} из "реагировать";

class ExampleComponent расширяет Component {
  constructor (props) {
    супер (реквизит);

    this.state = {
      статьи: [
        {title: "Руководство по React Redux для начинающих", id: 1},
        {title: "Учебник по TypeScript для начинающих", id: 2}
      ]
    };
  }

  render () {
    const {статьи} = this.state;
    return 
    {article.map (el =>
  • {el.title}
  • )}
; } }

Компонент React с отслеживанием состояния - это класс JavaScript (с хуками React, которые больше не используются).

В компоненте React состояние содержит данные, которые могут отображаться пользователю . Состояние в React также может изменяться в ответ на действия и события : на самом деле вы можете обновить состояние локального компонента с помощью this.setState () .

Итак, обычно типичное приложение JavaScript имеет состояние .Например, состояние:

  • что видит пользователь (данные)
  • данные, которые мы получаем из API
  • URL
  • элементы, выбранные на странице
  • возможных ошибок для показа пользователю

Ознакомившись с основами, давайте теперь поговорим о , какую проблему пытается решить Redux .

Какую проблему решает Redux?

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

Даже простое одностраничное приложение может выйти из-под контроля без четких границ между всеми слоями приложения. . Это особенно верно в отношении React.

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

К сожалению, сегодня в компоненты внешнего интерфейса вбивается тонна логики . Есть ли альтернатива этой агонии?

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

Еще лучше, Redux может содержать бизнес-логику на своем собственном уровне (промежуточное программное обеспечение) вместе с кодом для выборки данных. У этого подхода много преимуществ.

В следующих разделах мы увидим, когда и как использовать Redux в ваших приложениях. . Сначала пару слов о типичном вопросе: «Следует ли мне использовать Redux»?

Учебник по

React Redux: следует ли использовать Redux?

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

В React, например, есть много способов избежать использования Redux: дочерние реквизиты, контекстный API .

Но для средних и крупных проектов я всегда считал Redux (или его эквивалент) почти обязательным: библиотеки управления состоянием прекрасно сохраняют логику и поведение, абстрагированные от UI . Тестируемость пользовательского интерфейса стремительно растет, а значит, и продуктивность разработчика .Если вы посмотрите на это с другой точки зрения, вы можете возразить, что Redux имеет свою цену. Он добавляет вашему приложению еще один уровень абстракции.

Какую стоимость вы готовы заплатить? Сложные компоненты внешнего интерфейса или несколько уровней абстракций ?

Хватит говорить. В следующем разделе мы начнем создавать доказательство концепции, чтобы представить:

  • Основные принципы Redux
  • Redux вместе с React

Опять же, убедитесь, что у вас есть среда разработки React, готовая к использованию .

Учебник по

React Redux: знакомство с магазином Redux

Когда я впервые обратился к Redux, я был сбит с толку. Слишком много терминологии: действие , редуктор, промежуточное ПО . Но помимо этого мне было непонятно, как были склеены все движущиеся части ? Были какие-то миньоны что ли? В Redux нет миньонов (к сожалению) .

То, что управляет всеми винтиками, - это магазин . Повторяю со мной: в магазине .Хранилище в Redux - это своего рода волшебство, и хранит все состояние приложения.

Итак, давайте создадим магазин , чтобы начать играть с Redux. Перейдите в среду разработки React и установите Redux:

  cd react-redux-tutorial

npm i redux --save-dev  

Создать каталог для магазина:

Затем создайте новый файл src / js / store / index.js и инициализируйте хранилище:

 

import {createStore} из "redux";
импортировать rootReducer из "../reducers/index ";

const store = createStore (rootReducer);

экспорт магазина по умолчанию;  

Как видите, хранилище является результатом вызова createStore , функции из библиотеки Redux. createStore принимает в качестве первого аргумента редуктор, и в нашем случае мы передали rootReducer (еще не представленный).

Вы также можете передать начальное состояние в createStore , что полезно для рендеринга на стороне сервера и предварительной загрузки состояния , но пока нас это не интересует.Самая важная концепция, которую следует понять, заключается в том, что состояние в Redux исходит от редукторов . Повторим: редукторы создают состояние вашего приложения .

Вооружившись этими знаниями, давайте перейдем к , нашему первому редуктору Redux .

Смотрите ветку на Github

Учебное пособие по

React Redux: знакомство с редукторами Redux

Что такое редуктор? Редуктор Redux - это просто функция JavaScript . Он принимает два параметра : текущее состояние и действие (подробнее о действиях скоро).

В типичном компоненте React локальное состояние может быть изменено на месте. В Redux этого делать нельзя. Третий принцип Redux (изложенный его создателем) предписывает, что состояние является неизменным и не может измениться на месте .

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

В нашем примере мы создадим простой редуктор , который принимает начальное состояние и действие в качестве параметров.Создайте каталог для корневого редуктора:

Затем создайте новый файл src / js / reducers / index.js :

  const initialState = {
  статьи: []
};

function rootReducer (state = initialState, action) {
  вернуть состояние;
};

экспортировать rootReducer по умолчанию;  

Обратите внимание, как начальное состояние передается как параметр по умолчанию . Но с теперь наш редуктор ничего не делает, кроме возврата исходного состояния .

В следующем разделе мы добавим в микс действие , и все станет интересно.

Смотрите ветку на Github

Учебник по

React Redux: знакомство с действиями Redux и именованными константами

Редукторы

Redux, без сомнения, являются наиболее важной концепцией в Redux. Редукторы создают состояние приложения. Но как редуктор узнает, когда нужно сгенерировать следующее состояние?

Второй принцип Redux гласит, что единственный способ изменить состояние - это отправить сигнал в магазин. Этот сигнал - действие .Таким образом, « отправляет действие » означает, что отправляет сигнал в магазин.

Запутались? Обнадеживает то, что действия Redux - это не что иное, как объекты JavaScript. Так выглядит действие:

  {
  тип: 'ADD_ARTICLE',
  полезная нагрузка: {title: 'React Redux Tutorial', id: 1}
}  

Как видите, это объект JavaScript с двумя свойствами: тип и полезная нагрузка .

Свойство type определяет, как должно изменяться состояние, и оно всегда требуется Redux.Вместо этого свойство payload описывает, что следует изменить, и может быть опущено , если у вас нет новых данных для сохранения в магазине.

В качестве передовой практики в Redux мы заключаем каждое действие в функцию , чтобы создание объекта было абстрагировано. Такая функция носит имя создателя действия : давайте соберем все вместе, создав простой создатель действия.

Создать каталог для действий:

Затем создайте новый файл src / js / actions / index.js :

 

функция экспорта addArticle (payload) {
  вернуть {тип: "ADD_ARTICLE", полезная нагрузка}
};  

Вы можете заметить, что свойство типа является строкой. Строки склонны к опечаткам и дублируют , поэтому лучше объявлять действия как константы . Создайте для них новую папку:

  mkdir -p src / js / constants  

Затем создайте новый файл src / js / constants / action-types.js :

 

экспортная константа ADD_ARTICLE = "ADD_ARTICLE";  

Теперь откройте снова src / js / actions / index.js и обновите действие, чтобы использовать типы действий:

 

импортировать {ADD_ARTICLE} из "../constants/action-types";

функция экспорта addArticle (payload) {
  вернуть {тип: ADD_ARTICLE, полезная нагрузка};
}  

Как видите, мы начинаем работать с несколькими файлами. Это главная неприятность Redux для большинства людей. Вы можете следовать соглашению Redux duck, если хотите, оно хранит все связанные с Redux элементы в одном файле.

На один шаг ближе к тому, чтобы иметь работающее приложение Redux, но сначала нам нужно настроить редуктор для перехвата нового действия .

Смотрите ветку на Github

Рефакторинг редуктора

Мы оставили последний раздел со следующим вопросом: как редуктор узнает, когда генерировать следующее состояние ? Ключевым моментом здесь является магазин Redux. Когда действие отправлено, хранилище пересылает сообщение (объект действия) редуктору .

В этот момент редуктор говорит: «О, давайте посмотрим на свойство type этого действия». Затем , в зависимости от типа действия, редуктор создает следующее состояние , в конечном итоге объединяет полезную нагрузку действия в новое состояние.

Ранее мы создали редуктор, который ничего не делает. Давайте исправим! Откройте src / js / reducers / index.js и обновите reducer с помощью оператора if для , проверяющего тип действия :

 

импортировать {ADD_ARTICLE} из "../constants/action-types";

const initialState = {
  статьи: []
};

function rootReducer (state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    state.articles.push (действие.payload);
  }
  вернуть состояние;
}

экспортировать rootReducer по умолчанию;  

Также есть строка кода, которая переводит полезную нагрузку действия в начальное состояние .Кажется, поступить правильно. А вот это неправильно ! Наш редуктор нарушает основной принцип Redux: неизменность .

Array.prototype.push - это нечистая функция . : она изменяет исходный массив. Но это еще не все. Мы также меняем исходное состояние на месте.

Нам нужно исправить. Сначала мы можем вернуть новый объект JavaScript с Object.assign . Таким образом, мы сохраняем исходное состояние без изменений. Затем мы можем использовать массив .prototype.concat вместо Array.prototype.push для сохранения исходного массива:

  импортировать {ADD_ARTICLE} из "../constants/action-types";

const initialState = {
  статьи: []
};

function rootReducer (state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    return Object.assign ({}, состояние, {
      статьи: state.articles.concat (action.payload)
    });
  }
  вернуть состояние;
}

экспортировать rootReducer по умолчанию;  

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

  • используйте оператор concat, slice или spread для массивов
  • используйте Object.assign или объект распространения объектов

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

В следующем разделе мы поиграем с Redux с консоли браузера . Держись крепче!

Смотрите ветку на Github

Учебник по

React Redux: методы хранилища Redux

Обещаю, это будет очень быстро.

Вы можете быть удивлены, узнав, что Redux представляет собой небольшую библиотеку (2 КБ), а наиболее важные методы - это всего три :

  • getState для чтения текущего состояния приложения
  • отправка для отправки акции
  • подписаться на для прослушивания изменений состояния

Мы будем играть с ними в консоли браузера. Для этого нам нужно экспортировать хранилище и созданное нами действие как глобальные переменные.Создайте новый файл с именем src / js / index.js и поместите туда следующий код:

  импортный магазин из "../js/store/index";
импортировать {addArticle} из "../js/actions/index";

window.store = магазин;
window.addArticle = addArticle;  

Теперь откройте src / index.js , очистите его содержимое и обновите его следующим образом:

  индекс импорта из "./js/index";  

Теперь запустите сервер разработки с:

перейдите по адресу http: // localhost: 3000 / и откройте консоль с помощью F12.Начните с чтения текущего состояния :

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

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

Зарегистрируйте обратный вызов с помощью:

  store.subscribe (() => console.log ('Смотри, мама, Redux !!'));  

Чтобы изменить состояние в Redux, нам нужно отправить действие . Чтобы отправить действие, мы вызовем метод отправки. На данный момент у нас есть одно действие: addArticle для добавления нового элемента в состояние. Отправим действие с:

  store.dispatch (addArticle ({title: 'Учебное пособие по React Redux для начинающих', id: 1}));  

Сразу после выполнения приведенного выше кода вы должны увидеть «Смотри ма, Redux !!». Чтобы убедиться, что состояние изменилось, запустите снова:

И все. Это Redux в простейшем виде. Это было сложно?

Как только вы почувствуете себя уверенно, переходите к следующим разделам. Мы сразу перейдем к , соединяющему React с Redux !

Учебник

React Redux: подключение React к Redux

После изучения Redux я понял, что это не так уж и сложно. Я знал, как получить доступ к текущему состоянию с помощью getState. Я знал, как отправить действие с помощью отправки и как отслеживать изменения состояния с помощью подписки.

Но я не знал, как соединить вместе React и Redux.Я спрашивал себя: следует ли мне вызывать getState из React? Как отправить действие из компонента React? И так далее.

Redux не зависит от фреймворка . Вы можете использовать его с ванильным Javascript. Или с Angular. Или с React. Есть привязки для объединения Redux с вашим любимым фреймворком / библиотекой.

Для React существует react-redux , библиотека, для которой вам нужно изучить только один метод: подключить . Что оно делает? Неудивительно, что связывает компонент React с хранилищем Redux .

Вы будете использовать connect с двумя или тремя аргументами в зависимости от варианта использования:

  • a функция mapStateToProps (вы можете назвать ее также "select")
  • a mapDispatchToProps функция

mapStateToProps делает именно то, что предполагает его название: он связывает часть состояния Redux с реквизитами компонента React . Таким образом, подключенный компонент React получит доступ к той части магазина, которая ему нужна .

mapDispatchToProps делает нечто подобное, но для действий. mapDispatchToProps связывает действия Redux с реквизитами React . Таким образом, подключенный компонент React сможет отправлять сообщения в хранилище .

В следующем разделе мы, наконец, запачкаем руки. Мы создадим очень простое приложение из трех компонентов:

  • компонент приложения
  • Компонент списка для отображения статей
  • Компонент формы для добавления новых статей

React Redux tutorial: компонент приложения и хранилище Redux

Перед запуском установите react-redux с:

  npm i react-redux --save-dev  

Я сказал, что mapStateToProps связывает часть состояния Redux с реквизитами компонента React.Вы можете задаться вопросом: достаточно ли этого для соединения Redux с React ? Нет, это не так. Нам также нужен провайдер , высокоуровневый компонент из react-redux .

Откройте src / index.js , удалите все и обновите файл следующим кодом:

  импортировать React из "react";
import {render} из "react-dom";
импортировать {Provider} из "react-redux";
импортировать магазин из "./js/store/index";
импортировать приложение из "./js/components/App";

визуализировать (
  
    <Приложение />
  ,
  документ.getElementById ("корень")
);  

Как видите, Provider завершает ваше приложение React и сообщает ему обо всем хранилище Redux.

Теперь создадим компонент приложения. Ничего особенного: приложение должно импортировать компонент List и отрисовывать себя. Создайте каталог для хранения компонентов:

  mkdir -p SRC / JS / компоненты  

и новый файл с именем src / js / components / App.js :

 
импортировать React из "react";
Список импорта из "./Список";

const App = () => (
  

Статьи

<Список />
); экспортировать приложение по умолчанию;

Сохраните и закройте файл, затем перейдите к созданию списка.

Учебник по

React Redux: список компонентов и состояние Redux

Пока ничего особенного не сделали. Но наш новый компонент List будет взаимодействовать с хранилищем Redux .

Краткое резюме: ключ для , соединяющий компонент React с Redux, - это connect .Connect принимает хотя бы один аргумент.

Поскольку мы хотим, чтобы List получал список статей, необходимо установить соединение state.articles с компонентом. Как? С mapStateToProps . Обратите внимание, что «mapStateToProps» - это просто соглашение, большинство разработчиков, например, используют «select».

Создайте новый файл с именем src / js / components / List.js . Должно получиться так:

 

импортировать React из "react";
импорт из "react-redux";

const mapStateToProps = state => {
  вернуть {статьи: состояние.статьи};
};

const ConnectedList = ({статьи}) => (
  
    {article.map (el => (
  • {el.title}
  • ))}
); список констант = подключение (mapStateToProps) (ConnectedList); экспорт списка по умолчанию;

Компонент List получает опору article , которая является копией массива статей, который мы видели в состоянии Redux. Происходит от редуктора:

  const initialState = {
  статьи: []
};

function rootReducer (state = initialState, action) {
  если (действие.type === ADD_ARTICLE) {
    return Object.assign ({}, состояние, {
      статьи: state.articles.concat (action.payload)
    });
  }
  вернуть состояние;
}  

Всегда помните: состояние редуктора исходит от редуктора .

Наконец, компонент экспортируется как список. Список является результатом соединения компонента ConnectedList без сохранения состояния с хранилищем Redux.

Все еще не уверены? Чтобы понять, как работает Connect, потребуется время. . Но не бойтесь, путь к изучению Redux вымощен «ах-ха» моментами .

Я предлагаю сделать перерыв для изучения как connect, так и mapStateToProps.

Перейдите к следующему разделу, когда будете готовы!

Учебное пособие по

React Redux: компонент формы и действия Redux

Компонент Form, который мы собираемся создать, немного сложнее, чем List. Это форма для добавления новых элементов в наше приложение, и для этого мы будем использовать класс JavaScript.

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

Компонент класса поможет сохранить некоторое локальное состояние, например входные данные формы. Он также получает действие Redux. Таким образом, он может обновить глобальное состояние, отправив действие addArticle.

Создайте новый файл в src / js / components / Form.js со следующим кодом:

 
импортировать React, {Component} из "react";
импорт из "react-redux";
импортировать {addArticle} из "../actions/index";

function mapDispatchToProps (dispatch) {
  возвращение {
    addArticle: article => отправка (addArticle (статья))
  };
}

class ConnectedForm расширяет Component {
  constructor (props) {
    супер (реквизит);
    этот.state = {
      заглавие: ""
    };
    this.handleChange = this.handleChange.bind (это);
    this.handleSubmit = this.handleSubmit.bind (это);
  }

  handleChange (event) {
    this.setState ({[event.target.id]: event.target.value});
  }

  handleSubmit (event) {
    event.preventDefault ();
    const {название} = this.state;
    this.props.addArticle ({название});
    this.setState ({название: ""});
  }
  render () {
    const {название} = this.state;
    возвращение (
      
<ввод type = "текст" значение = {название} onChange = {это.handleChange} />
); } } const Form = connect ( значение NULL, mapDispatchToProps ) (ConnectedForm); экспорт формы по умолчанию;

Краткое описание компонента:

  • стандартный материал React рядом с mapDispatchToProps и подключение
  • mapDispatchToProps связывает действия Redux с реквизитами React
  • метод handleSubmit отправляет действие

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

  function mapDispatchToProps (dispatch) {
  возвращение {
    addArticle: article => отправка (addArticle (статья))
  };
}  

В качестве альтернативы вы также можете передать mapDispatchToProps как объект.Взгляните сюда.

Наконец, компонент экспортируется как форма. Форма - это результат подключения ConnectedForm к хранилищу Redux.

Примечание: первый аргумент для подключения должен быть нулевым, когда mapStateToProps отсутствует, как в нашем примере . Или вы получите TypeError: отправка - это не функция.

Наши комплектующие готовы! Теперь обновите приложение, чтобы включить компонент формы:

  импортировать React из "react";
импортировать список из "./List";
Импортировать форму из "./ Форма ";

const App = () => (
  <>
    

Статьи

<Список />

Добавить новую статью

<Форма />
); экспортировать приложение по умолчанию;

Запустите сервер разработки с:

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

Ничего особенного, но все же полезно для демонстрации работы React и Redux!

Компонент List слева обращается к хранилищу Redux.Он будет повторно отображаться всякий раз, когда вы добавляете новый элемент.

Вы сделали это! Но мы еще не закончили! В следующем разделе мы рассмотрим промежуточное ПО Redux . Держись крепче!

Смотрите ветку на Github

Учебник по

React Redux: что такое промежуточное ПО Redux?

Пока что мы видели строительные блоки Redux: магазин , ГАИ. Reducers , что делает состояние в Redux.

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

Теперь представьте себе следующий сценарий: вам нужно запретить пользователям создавать статьи с определенными словами внутри заголовка. Давайте посмотрим на handleSubmit в Form.js :

  handleSubmit (событие) {
    event.preventDefault ();
    const {название} = this.state;
    this.props.addArticle ({название});
    this.setState ({название: ""});
  }  

Мы можем просто добавить чек перед this.props.addArticle правильно? Это может быть что-то вроде этого:

  handleSubmit (событие) {
    event.preventDefault ();
    const {название} = this.state;
    const disabledWords = ['спам', 'деньги'];
    const foundWord = disabledWords.filter (word => title.includes (word))
    if (foundWord) {
      вернуть this.props.titleForbidden ();
    }
    this.props.addArticle ({название});
    this.setState ({название: ""});
  }  

Разве не весь смысл Redux в перемещении логики из наших компонентов React ? И что? Можем ли мы проверить свойство title внутри редуктора? Может быть! Пока там отправим другое действие в ответ на запрещенное слово... но как мне получить доступ к диспетчеризации внутри редуктора?

Понятно, что мы хотим чего-то другого. Похоже, мы хотим, чтобы проверила полезную нагрузку действия (и свойство title), прежде чем действие перейдет в редуктор . Должен быть способ для подключаться к потоку приложения. Угадайте, что это именно то, что промежуточное ПО Redux делает .

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

В своей базовой форме промежуточное ПО Redux - это функция, возвращающая функцию, которая принимает следующий параметр в качестве параметра. Затем внутренняя функция возвращает другую функцию, которая выполняет действие в качестве параметра и, наконец, возвращает next (action) . Вот как это выглядит:

  functionhibitedWordsMiddleware () {
  return function (next) {
    return function (action) {
      
      вернуться далее (действие);
    }
  }
}  

Последний пункт действительно важен: вы всегда должны вызывать next (action) в промежуточном программном обеспечении.Если вы его забудете, Redux остановится, и никакие другие действия не достигнут редуктора. next (действие) перемещает приложение вперед на , вызывая следующее промежуточное ПО в цепочке .

В промежуточном программном обеспечении вы также можете получить доступ к getState и dispatch :

  functionhibitedWordsMiddleware ({getState, dispatch}) {
  return function (next) {
    return function (action) {
      
      вернуться далее (действие);
    }
  }
}  

Интересно также то, что промежуточное ПО не завершает работу после next (action) .Если вас интересует , считывающее следующее состояние приложения после запуска цепочки промежуточного программного обеспечения , вы можете зафиксировать его с помощью getState после next (action) :

  functionhibitedWordsMiddleware ({getState, dispatch}) {
  return function (next) {
    return function (action) {
      
      const nextAction = next (действие);
      
      состояние константы = getState ();
      
      return nextAction;
    }
  }
}  

Тем не менее, не забудьте вернуть следующее действие в конце.

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

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

Учебник

React Redux: ваше первое промежуточное ПО Redux

Промежуточное ПО, которое мы собираемся создать, должно проверять полезную нагрузку действия. Есть много преимуществ от использования промежуточного программного обеспечения Redux :

  • большая часть логики может находиться вне библиотеки пользовательского интерфейса
  • Промежуточное ПО

  • становится повторно используемым элементом логики, около
  • легко рассуждать
    Промежуточное ПО

  • можно тестировать изолированно

Итак, давайте запачкаем руки. Создайте новую папку для промежуточного программного обеспечения:

  mkdir -p src / js / промежуточное ПО  

Теперь создайте новый файл с именем src / js / middleware / index.js . Структура нашего первого промежуточного программного обеспечения должна быть такой:

  functionhibitedWordsMiddleware ({dispatch}) {
  return function (next) {
    return function (action) {
      
      вернуться далее (действие);
    }
  }
}  

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

Кроме того, проверка должна запускаться только тогда, когда действие имеет тип ADD_ARTICLE . Это имеет смысл. Как насчет этого:

  импортировать {ADD_ARTICLE} из "../constants/action-types";

const disabledWords = ["спам", "деньги"];

функция экспорта запрещеноWordsMiddleware ({dispatch}) {
  return function (next) {
    return function (action) {
      
      if (action.type === ADD_ARTICLE) {
        
        const foundWord = disabledWords.filter (word =>
          действие.payload.title.includes (слово)
        );

        if (foundWord.length) {
          возвратная отправка ({type: "FOUND_BAD_WORD"});
        }
      }
      вернуться далее (действие);
    };
  };
}  

Вот что делает промежуточное ПО: при типе действия ADD_ARTICLE проверяет, не содержит ли action.payload.title плохое слово. Если это так, то отправьте действие типа FOUND_BAD_WORD , в противном случае позволит следующему промежуточному программному обеспечению выполнить .

А теперь пришло время подключить allowedWordsMiddleware к магазину Redux.Для этого нам нужно импортировать наше промежуточное ПО, еще одну утилиту из Redux (applyMiddleware), а затем приготовить все вместе.

Откройте src / js / store / index.js и измените файл следующим образом:

 

import {createStore, applyMiddleware} из "redux";
импортировать rootReducer из "../reducers/index";
импортировать {disabledWordsMiddleware} из "../middleware";

const store = createStore (
  rootReducer,
  applyMiddleware (запрещено использоватьСреднее ПО)
);

экспорт магазина по умолчанию;  

Примечание : если вы хотите включить Redux Dev Tools, используйте этот код.

Сохраните и закройте файл, запустите npm start и проверьте, работает ли промежуточное ПО. Попробуйте добавить статью со словом «деньги» в ее названии, и вы не увидите, что новая статья появится в списке .

Промежуточное ПО работает! Отличная работа! В следующих разделах мы рассмотрим асинхронные действия в Redux с Redux Thunk и Redux Saga .

Посмотреть урок 5 курса Redux, работа с промежуточным программным обеспечением

Смотрите ветку на Github

Учебник по

React Redux: асинхронные действия в Redux, наивный способ

До сих пор мы имели дело с синхронными данными .То есть отправляет действие синхронно . Нет AJAX, никаких обещаний. Мы возвращаем простой объект от наших создателей действий. И когда действие достигает редуктора, мы возвращаем следующее состояние.

Теперь предположим, что мы хотим, чтобы извлекал данные из API . В React вы бы позвонили в componentDidMount и завершили бы его. А как насчет Redux? Какое место подходит для вызова асинхронных функций ? Давай подумаем об этом.

Редукторы? Ни за что. Редукторы должны оставаться сухими и чистыми.Редуктор - не лучшее место для асинхронной логики.

Действия? Как я должен это делать? Действия в Redux - это простые объекты. А как насчет создателей действий? Создатель действий - это функция, и это выглядит как хорошее место для вызова API! Давайте попробуем.

Мы создадим новое действие с именем getData . Это действие вызывает API с Fetch и возвращает действие Redux.

Откройте src / js / actions / index.js и создайте новое действие с именем getData :

 



функция экспорта getData () {
  return fetch ("https: // jsonplaceholder.typicode.com/posts ")
    .then (ответ => response.json ())
    .then (json => {
      вернуть {тип: "DATA_LOADED", полезная нагрузка: json};
    });
}  

В этом есть смысл. Будет ли работать ? Давайте подключим компонент React для отправки getData из componentDidMount . mapDispatchToProps (на этот раз с сокращенной формой объекта) сопоставит создателей действий Redux с реквизитами нашего компонента. Создайте новый компонент React в src / js / components / Posts.js :

  импортировать React, {компонент} из "реагировать";
импорт из "react-redux";
импортировать {getData} из "../actions/index";

экспортный класс Post расширяет компонент {
  constructor (props) {
    супер (реквизит);
  }

  componentDidMount () {
    
    this.props.getData ();
  }

  render () {
    return null;
  }
}

экспортировать соединение по умолчанию (
  значение NULL,
  { получить данные }
)(Почта);  

Наконец, обновите src / js / components / App.js , чтобы использовать новый компонент:

  импортировать React из "react";
Список импорта из "./Список";
импортировать форму из "./Form";
импортировать сообщения из "./Posts";

const App = () => (
  <>
    

Статьи

<Список />

Добавить новую статью

<Форма />

Сообщения API

<Сообщение />
); экспортировать приложение по умолчанию;

Сохраните и закройте файлы, запустите приложение и посмотрите на консоль: «Ошибка: Действия должны быть простыми объектами.Используйте настраиваемое промежуточное ПО для асинхронных действий ». Мы не можем вызвать Fetch из создателя действий в Redux . Что теперь?

Для того, чтобы все работало, нам нужно специальное промежуточное ПО. К счастью, для нас есть кое-что готовое: redux-thunk .

Асинхронные действия в Redux с Redux Thunk

Мы только что узнали, что вызов Fetch от создателя действия не работает .

Это потому, что Redux ожидает объекты как действия, но мы пытаемся вернуть Promise.

С помощью redux-thunk (это промежуточное программное обеспечение) мы можем решить проблему и вернуть функции от создателей действий . Таким образом, мы можем вызывать API, задерживать отправку действия и т. Д.

Сначала нам нужно установить промежуточное ПО с:

  npm i redux-thunk --save-dev  

Теперь загрузим промежуточное ПО в src / js / store / index.js :

  import {createStore, applyMiddleware, compose} из "redux";
импортировать rootReducer из "../reducers/index ";
импортировать {disabledWordsMiddleware} из "../middleware";
импортировать thunk из "redux-thunk";

const storeEnhancers = window .__ REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || сочинять;

const store = createStore (
  rootReducer,
  storeEnhancers (applyMiddleware (biddenWordsMiddleware, thunk))
);

экспорт магазина по умолчанию;  

На этом этапе нам нужно выполнить рефакторинг getData , чтобы использовать redux-thunk. Откройте src / js / actions / index.js и обновите создатель действий следующим образом:

  экспортная функция getData () {
  функция возврата (отправка) {
    return fetch ("https: // jsonplaceholder.typicode.com/posts ")
      .then (ответ => response.json ())
      .then (json => {
        отправка ({тип: "DATA_LOADED", полезная нагрузка: json});
      });
  };
}  

Это сокращение! Чтобы получить доступ к состоянию внутри создателя действия, вы также можете добавить getState в список параметров.

Также обратите внимание на использование отправки внутри , а затем для отправки следующего действия после завершения Fetch.

Теперь мы готовы обновить наш редуктор новым типом действия.

Откройте src / js / reducers / index.js и добавьте новый оператор if. Мы также можем добавить новый ключ внутри начального состояния для сохранения статей из API:

  импортировать {ADD_ARTICLE} из "../constants/action-types";

const initialState = {
  статьи: [],
  удаленные статьи: []
};

function rootReducer (state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    return Object.assign ({}, состояние, {
      статьи: state.articles.concat (action.payload)
    });
  }

  если (действие.type === "DATA_LOADED") {
    return Object.assign ({}, состояние, {
      remoteArticles: state.remoteArticles.concat (action.payload)
    });
  }
  вернуть состояние;
}

экспортировать rootReducer по умолчанию;  

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

Наконец, мы готовы обновить наш компонент Post для отображения наших "удаленных" сообщений. Мы будем использовать mapStateToProps (опять же, не стесняйтесь называть эту функцию select) для выбора десяти сообщений:

  импортировать React, {компонент} из "реагировать";
импорт из "react-redux";
импортировать {getData} из "../actions/index ";

экспортный класс Post расширяет компонент {
  constructor (props) {
    супер (реквизит);
  }

  componentDidMount () {
    this.props.getData ();
  }

  render () {
    возвращение (
      
    {this.props.articles.map (el => (
  • {el.title}
  • ))}
); } } function mapStateToProps (состояние) { возвращение { статьи: state.remoteArticles.slice (0, 10) }; } экспортировать соединение по умолчанию ( mapStateToProps, { получить данные } )(Почта);

Сохраните и закройте файлы, запустите приложение, и все должно работать нормально ! Отличная работа!

Напомним: Redux не понимает других типов действий, кроме простого объекта .

Если вы хотите переместить асинхронную логику из React в Redux и иметь возможность возвращать функции вместо простых объектов, вы должны использовать собственное промежуточное ПО.

redux-thunk - это промежуточное ПО для Redux . С помощью redux-thunk вы можете возвращать функции от создателей действий, а не только объекты. Вы можете выполнять асинхронную работу внутри своих действий и отправлять другие действия в ответ на вызовы AJAX.

Когда использовать redux-thunk? redux-thunk - хорошее промежуточное программное обеспечение, которое очень хорошо работает для большинства случаев использования .Но если ваша асинхронная логика включает более сложные сценарии или если у вас есть особые требования, то сага о redux может быть лучше.

В следующем разделе мы рассмотрим это. Держись крепче!

Смотреть курс Redux, лекция 6, асинхронные действия с redux-thunk

Смотрите ветку на Github

Учебник по

React Redux: знакомство с Redux Saga

redux-thunk отлично подходит для многих проектов. Вы также можете полностью пропустить redux-thunk и перенести асинхронную логику на настраиваемое промежуточное ПО .Но в действительности асинхронные действия сложнее протестировать и организовать.

По этой причине большинство разработчиков предпочитают альтернативный подход: redux-saga .

Что такое redux-saga ? redux-saga - это промежуточное ПО Redux для управления побочными эффектами . С redux-saga у вас может быть отдельный поток в вашем приложении для обработки нечистых действий: вызовов API, доступа к хранилищу и т. Д.

redux-saga отличается от асинхронного действия как синтаксисом, так и организацией кода.С помощью redux-thunk вы можете поместить вызов API непосредственно в создатель действия, а в redux-saga вы можете четко разделить синхронную и асинхронную логику .

Стоит отметить, что redux-saga не использует обычные функции JavaScript. Вы увидите много звездочек и «уступок» в ваших сагах. Эти звездочки обозначают , функции генератора !

Функции генератора в JavaScript - это функции, которые можно приостанавливать и возобновлять по запросу . redux-saga в значительной степени полагается на функции генератора, но хорошо то, что вам не нужно вызывать next () в вашем коде.redux-saga делает это за вас под капотом.

Написание вашей первой Redux Saga

В этом разделе мы проведем рефакторинг нашего кода, чтобы использовать сагу о Redux вместо преобразователя. Я не буду описывать весь API Saga в этом посте, так что, пожалуйста, потерпите меня. Мы просто рассмотрим несколько методов.

Перед тем, как начать, установите redux saga с:

  npm i redux-saga --save-dev  

Теперь мы можем провести рефакторинг нашего асинхронного действия и удалить вызов выборки.С этого момента наш создатель действий будет просто отправлять простое действие. Откройте src / js / actions / index.js и измените getData , чтобы вернуть простое действие с именем DATA_REQUESTED :

  экспортная функция getData () {
  return {type: "DATA_REQUESTED"};
}  

Действие DATA_REQUESTED будет перехвачено сагой Redux с takeEvery . Вы можете представить, что takeEvery принимает каждое действие DATA_REQUESTED , проходящее внутри нашего приложения, и начинает некоторую работу в ответ на это действие.

Итак, как вы структурируете сагу? Сага о сокращении может жить в одном файле, содержащем :

  • a рабочая функция
  • a функция наблюдателя

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

Рабочая сага вызовет удаленный API с вызовом из redux-saga / effects.Когда данные загружены, мы можем отправить другое действие из нашей саги с положить , опять же из redux-saga / effects.

Вооружившись этими знаниями, мы можем создать нашу первую сагу о Redux. Сначала создайте новую папку для хранения ваших саг:

Затем создайте новый файл с именем api-saga.js в src / js / sagas . А вот и наша сага:

  import {takeEvery, call, put} из "redux-saga / effects";

функция экспорта по умолчанию * watcherSaga () {
  yield takeEvery ("DATA_REQUESTED", workerSaga);
}

function * workerSaga () {
  пытаться {
    полезная нагрузка const = yield call (getData);
    yield put ({тип: "DATA_LOADED", полезная нагрузка});
  } catch (e) {
    yield put ({тип: "API_ERRORED", полезная нагрузка: e});
  }
}  

Давайте сделаем перерыв, чтобы прочитать логический ход нашей саги.

Демистификация вашей первой саги о сокращении

Взгляните на приведенный выше код. Вот как это работает:

  1. выполняет каждое действие с именем DATA_REQUESTED и для каждого действия запускает рабочую сагу
  2. внутри саги о работниках вызывает функцию с именем getData
  3. , если функция завершается успешно, отправьте (поместите) новое действие с именем DATA_LOADED вместе с полезной нагрузкой
  4. , если функция не работает, отправьте (поместите) новое действие с именем API_ERRORED вместе с полезной нагрузкой (ошибкой)

Единственное, чего нам не хватает в нашем коде, это getData .Снова откройте src / js / sagas / api-saga.js и добавьте функцию:

  import {takeEvery, call, put} из "redux-saga / effects";

функция экспорта по умолчанию * watcherSaga () {
  yield takeEvery ("DATA_REQUESTED", workerSaga);
}

function * workerSaga () {
  пытаться {
    полезная нагрузка const = yield call (getData);
    yield put ({тип: "DATA_LOADED", полезная нагрузка});
  } catch (e) {
    yield put ({тип: "API_ERRORED", полезная нагрузка: e});
  }
}

function getData () {
  return fetch ("https: // jsonplaceholder.typicode.com/posts").then(response =>
    response.json ()
  );
}  

Наконец, мы можем подключить redux saga к нашему магазину redux. Откройте src / js / store / index.js и обновите магазин следующим образом:

  import {createStore, applyMiddleware, compose} из "redux";
импортировать rootReducer из "../reducers/index";
импортировать {disabledWordsMiddleware} из "../middleware";
импортировать createSagaMiddleware из "redux-saga";
импортировать apiSaga из "../sagas/api-saga";

const initialiseSagaMiddleware = createSagaMiddleware ();

const storeEnhancers = окно.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || сочинять;

const store = createStore (
  rootReducer,
  storeEnhancers (
    applyMiddleware (biddenWordsMiddleware, initialiseSagaMiddleware)
  )
);

initialiseSagaMiddleware.run (apiSaga);

экспорт магазина по умолчанию;  

Уведомление createSagaMiddleware и initialiseSagaMiddleware.run для запуска нашей саги. Теперь закройте и сохраните файл. Запустите npm start, и вы должны снова увидеть тот же результат, а удаленные сообщения правильно отображаются в браузере.

Поздравляем! Вы создали свою первую сагу о redux ! А теперь пара упражнений:

  • наш редуктор был готов к обработке DATA_LOADED вместе со своей полезной нагрузкой. Завершите редуктор для работы с API_ERRORED .
  • перемещают DATA_LOADED , API_ERRORED и DATA_REQUESTED в именованные константы.
  • нужно ли нам лучше учитывать ошибки выборки внутри getData?

КОД: вы можете получить доступ к полному примеру в response-redux-tutorial на Github.Клонируйте репо и проверьте самую последнюю ветку:

  git clone https://github.com/valentinogagliardi/react-redux-tutorial
компакт-диск React-redux-учебник
git checkout ваша первая редукция сага  

Смотрите ветку на Github

Саги и параметры

Рабочие саги принимают фактическое действие в качестве параметра:

  function * workerSaga (действие) {

}  

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