Рубрики
Без рубрики

Как сделать ваше приложение React полностью функционально, полностью реагирующим и способным обрабатывать все эти сумасшедшие …

Лука Matteeis, как сделать ваше приложение React полностью функционально, полностью реагирующим и способным обрабатывать все эти сумасшедшие побочные эффекты функциональные реактивные программирование (FRP) – это парадигма, которая в последнее время привлекла много внимания, особенно в фронтном мире JavaScript. Это перегруженный срок, но он описывает

Автор оригинала: FreeCodeCamp Community Member.

Лука Маттеис

Функциональное реактивное программирование (FRP) – это парадигма, которая в последнее время набрала много внимания, особенно в мире переднего мира JavaScript. Это перегруженный термин, но он описывает простую идею:

Реагируйте сам по себе не полностью функциональны, и не полностью реагирует. Но он вдохновлен некоторыми из концепций FRP. Функциональные компоненты Например, являются чистыми функциями по отношению к их реквизиту. И Они реагируют на рек или государственные изменения Отказ

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

В этой статье я расскажу о redux-cycles Промежуточное программное обеспечение Redux, которое поможет вам обрабатывать побочные эффекты и асинко-код в ваших реакстрационных приложениях в функциональном процессе – чертежу, которая еще не передается другим моделям Redux побочные эффекты – путем используя Cycle.js фреймворк.

Что такое побочные эффекты?

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

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

Вот несколько популярных способов обрабатывать побочные эффекты в Redux:

  1. Redux-Thunk – Укладывает код побочных эффектов внутри создателей действий
  2. Redux-Saga – делает ваши побочные эффекты логики декларативными с помощью SAGAS
  3. redux-наблюдаемый – использует реактивное программирование для модели побочных эффектов

Проблема в том, что ничто из них не являются чистыми, так и реактивными. Некоторые из них чистые (redux-Saga), в то время как другие являются реактивными (наблюдаемыми), но ни один из них не разделяет всеми понятиями, которые мы представили ранее о FRP.

Redux-cycles является чистым, так и реактивным.

Сначала мы впервые объясним эти функциональные и реактивные концепции – и почему вы должны заботиться. Затем мы объясним, как Redux-Cycles работает подробно.

Чистые побочные эффекты обрабатываются с циклом .js

HTTP-запрос, вероятно, является наиболее распространенным побочным эффектом. Вот пример HTTP-запроса с использованием Redux-Thunk:

function fetchUser(user) {  return (dispatch, getState) =>     fetch(`https://api.github.com/users/${user}`)}

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

То же самое относится к наблюдаемым redux:

const fetchUserEpic = action$ =>  action$.ofType(FETCH_USER)    .mergeMap(action =>      ajax.getJSON(`https://api.github.com/users/${action.payload}`)        .map(fetchUserFulfilled)    );

ajax.getjson () делает этот фрагмент императив кода.

Чтобы сделать HTTP-запрос чистым, вы не должны думать о «сделать HTTP-запрос сейчас», а скорее «позвольте мне описать, как я хочу, чтобы мой HTTP-запрос выглядеть как« и не беспокоиться о том, когда он на самом деле случается или кто делает это.

В Cycle.js Это, по сути, как вы кодируете все. Все, что вы делаете с рамками, – это создание описаний о том, что вы хотите сделать. Эти описания затем отправляются на эти вещи, называемые водители (через реактивные потоки), которые фактически заботятся о том, чтобы сделать HTTP-запрос:

function main(sources) {  const request$ = xs.of({    url: `https://api.github.com/users/foo`,  });
  return {    HTTP: request$  };}

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

Волшебство происходит благодаря водителям. Cycle.js знает, что когда ваша функция возвращает объект с Http . Ключ, ему необходимо обрабатывать сообщения, которые он получает из этого потока и выполняет HTTP-запрос соответственно (через драйвер HTTP).

Ключевым моментом является то, что вы не избавлялись от побочного эффекта – HTTP-запрос все еще должен произойти – но вы локализовали его за пределами вашего приложений.

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

Реактивные побочные эффекты

В более ранних примерах мы затронули реактивность. Там должно быть способ общаться с этими так называемыми водителями о «делать вещи во внешнем мире» и быть уведомленным о «вещах, которые происходят во внешнем мире».

Наблюдается (aka Streams) – идеальная абстракция для такого рода асинхронизации.

Всякий раз, когда вы хотите «сделать что-нибудь», вы издаете выходной поток, описание того, что вы хотите сделать. Эти выходные потоки называются раковины в мире Cycle.js.

Всякий раз, когда вы хотите «быть уведомленным о чем-то, что произошло», вы используете входной поток (называемый «| Источники ) и просто отобразитесь над значениями потока, чтобы узнать о том, что произошло.

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

function main(sources) {  const response$ = sources.HTTP    .select('foo')    .flatten()    .map(response => response);
  const request$ = xs.of({    url: `https://api.github.com/users/foo`,    category: 'foo',  });
  const sinks = {    HTTP: request$  };  return sinks;}

Драйвер HTTP знает о Http . ключ возвращен этой функцией. Это поток, содержащий описание HTTP-запроса для URL-адреса GitHub. Он говорит HTTP-драйвере: «Я хочу сделать запрос на этот URL».

Затем драйвер знает, что выполняет запрос и отправляет ответ на основную функцию в качестве источника ( источники. Http . ) – Обратите внимание, что раковины и источники используют один и тот же клавишу объекта.

Давайте объясним это снова: Мы используем источники. Http . Для «быть уведомленным о HTTP ответов». И мы возвращаемся мойки. Http . Чтобы «сделать HTTP-запросы».

Чтобы объяснить эту важную реактивный цикл вот анимация:

Это кажется контр-интуитивным по сравнению с обычным императивным программированием: почему код для чтения ответа существует до того, как код, ответственный за запрос?

Это потому, что не имеет значения, где код находится в FRP. Все, что вам нужно сделать, это отправить описания и слушать изменения. Заказ кода не важен.

Это позволяет очень легко рефакторировать код.

Представляем redux-циклы

На этом моменте вы можете спросить, что все это связано с моим приложением React?

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

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

Перехватывание и диспетчерничество redux Действия

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

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

Это именно то, что redux-cycles делает. Это промежуточное программное обеспечение, которое перехватывает действия Redux, вводят в действие реактивный цикл Cycle.js и позволяет выполнять другие побочные эффекты с использованием других драйверов. Затем он отправляет новые действия на основе ASYNC DataFlow, описанной в ваших функциях:

function main(sources) {  const request$ = sources.ACTION    .filter(action => action.type === FETCH_USER)    .map(action => ({      url: `https://api.github.com/users/${action.payload}`,      category: 'users',    }));  const action$ = sources.HTTP    .select('users')    .flatten()    .map(fetchUserFulfilled);  const sinks = {    ACTION: action$,    HTTP: request$  };  return sinks;}

В приведенном выше примере есть новый источник и раковина, представленные redux-cycles – Действие Отказ Но парадигма связи одинаково.

Он слушает действия, отправленные из мира redux, используя источники. ДЕЙСТВИЕ . И это отправляет новые действия в мир Redux, вернувшись мойки. ДЕЙСТВИЕ .

В частности, он излучает стандарт Flux Действия Объекты Отказ

Прохладно, что вы можете объединить вещи, происходящие из других драйверов. В предыдущем примере Вещи, происходящие в Http . Мир фактически вызывает изменения в Действие Мир и вице-версия Отказ

– Обратите внимание, что общение с redux происходит полностью через Действие источник/мойка. Водители Redux-Cycles обрабатывают фактическую рассылку для вас.

Как насчет более сложных приложений?

Как разрабатывает более сложные приложения, если вы просто пишете чистые функции, которые преобразуют потоки данных?

Оказывается, вы можете сделать в значительной степени что-нибудь, используя Уже построили драйверы Отказ Или вы можете легко создать свой собственный – вот простой драйвер, который регистрирует сообщения, записанные на его раковину.

run(main, {  LOG: msg$ => msg$.addListener({    next: msg => console.log(msg)  })});

Беги является частью Cycle.js, который запускает вашу основную функцию (первый аргумент) и пропускает вдоль всех драйверов (второй аргумент).

Redux-Cycles представляет два драйвера, которые позволяют вам общаться с redux; MakeActionDriver () & Makestatedriver () :

import { createCycleMiddleware } from 'redux-cycles';
const cycleMiddleware = createCycleMiddleware();const { makeActionDriver, makeStateDriver } = cycleMiddleware;
const store = createStore(  rootReducer,  applyMiddleware(cycleMiddleware));
run(main, {  ACTION: makeActionDriver(),  STATE: makeStateDriver()})

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

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

Сложный асинхронный поток данных

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

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

Редукс-наблюдаемый также позволяет писать сложные асинхронизированные потоки – они используют примечание мультиплексного веб-сайта в качестве их точки продажи – однако власть написания этих потоков в чистый Мода – это то, что действительно устанавливает Cycle.js друг от друга.

Тестирование с мраморными диаграммами

Последнее, но не менее важное, тестирование. Это где redux-циклы (и вообще все приложения Cycle.js) действительно сияет.

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

Использование замечательного @ Цикл/время Проект, вы даже можете рисовать Мраморные диаграммы и проверить свои функции очень визуальным образом:

assertSourcesSinks({  ACTION: { '-a-b-c----|': actionSource },  HTTP:   { '---r------|': httpSource },}, {  HTTP:   { '---------r|': httpSink },  ACTION: { '---a------|': actionSink },}, searchUsers, done);

Этот кусок кода Выполняет поиски Функция, передавая его конкретные источники в качестве ввода (первый аргумент). Учитывая эти источники, он ожидает, что функция возвращает предоставленные мойки (второй аргумент). Если это не так, утверждение не удается.

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

Когда Http . Источник излучает R (ответ), вы сразу ожидаете А (Действие) появиться в Действие раковина – они случаются одновременно. Однако, когда Действие Источник испускает всплеск -A-B-C , вы не ожидаете что-нибудь появиться в этот момент в Http . раковина.

Это потому, что поиски предназначен для расстройства действий, которые он получает. Он отправит только HTTP-запрос после 800 миллисекундов бездействия на потоке источника действия: он реализует функциональность автозаполнения.

Тестирование такого рода асинхронизированного поведения тривиальна с чистыми и реактивными функциями.

Заключение

В этой статье мы объяснили истинную силу FRP. Мы представили Cycle.js и его новые парадигмы. Cycle.js потрясающий список Это важный ресурс, если вы хотите узнать больше об этой технологии.

Использование Cycle.js самостоятельно – без реагирования или redux – требует немного выключателя в менталитете, но можно сделать, если вы готовы отказаться от некоторых технологий и ресурсов в сообществе React/Redux.

Redux-Cycles с другой стороны позволяет продолжать использовать все великие реагированные материалы, когда вы сможете намочить своими руками FRP и Cycle.js.

Особая благодарность Гоша Аринич и Ник Balestra для поддержания проекта наряду с собой и к Ник Джонстон Для доказательства чтения этой статьи.

Оригинал: “https://www.freecodecamp.org/news/how-to-make-your-react-app-fully-functional-fully-reactive-and-able-to-handle-all-those-crazy-e5da8e7dac10/”