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

Комплексное руководство по типу проверки реакции, Redux и React-Redux с потоком

Fabian Terh Всестороннее руководство по проверке реакции, Redux и React-redux с помощью статьи FlowThis делится на 4 раздела: тип проверки действия redux, создатели действия и редукторинг-библиотека текучести поток. Букет гидов на первом разделе

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

Fabian Terh

Эта статья разделена на 4 раздела:

  1. Тип проверки действий redux, создатели действия и редукторы
  2. Установка определений библиотеки потока
  3. Тип Проверка состояния приложения
  4. Тип Проверка магазина redux и отправка

Хотя на первом разделе есть куча гидов, которые являются неармымиленными полезными, я обнаружил только о незначительности статьи 3 и 4. После длительной сессии поиска Google, дайвинга в исходный код и проб и ошибку, я решил поставить Вместе то, что я узнал, и пишу этот учебный пособие как однократное руководство по типу проверки вашего ADTACT + Redux + Read-redux приложение с потоком.

1. Введите проверку действий redux, создатели действия и редукторы

Действия

Действия Redux по существу являются объектами Vanilla JavaScript с обязательным Тип свойство:

// This is an action{  type: 'INCREASE_COUNTER',  increment: 1}

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

const INCREASE_COUNTER = 'INCREASE_COUNTER';
// This is an action{  type: INCREASE_COUNTER,  increment: 1}

Проверка типа проста (мы имеем дело с регулярным JavaScript здесь):

type $action = {  type: 'INCREASE_COUNTER',  increment: number};

Обратите внимание, что вы не можете заменить буквальный тип строки с константой Увеличить_counter Отказ Это Ограничение потока самого.

Действия Создатели

Поскольку Action Creators – это просто функции, которые возвращают действия, мы все еще имеем дело с регулярным JavaScript. Вот как может выглядеть проверяемое действие типа

function increaseCounter(by: number): $action {  return {    type: INCREASE_COUNTER, // it's okay to use the constant here    increment: by  };}

Редукторы

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

// State shape{  counter: }

И поэтому ваш редуктор может выглядеть так:

const initialState = { counter: 0 };
function counter(state = initialState, action) {  switch (action.type) {    case INCREASE_COUNTER:      return Object.assign({}, state, {        counter: action.increment + state.counter      });        default:      return state;  }};

Примечание: в этом конкретном примере Object.Assign ({}, состояние, {...}) избыточно, потому что магазин состоит только из 1 пары ключа/значения. Я мог бы просто вернуть последний аргумент на функцию. Однако я включил полную реализацию для правильности.

Набрав состояние и редуктор достаточно просто. Вот набранный Версия вышеуказанного фрагмента:

type $state = {  +counter: number};
const initialState: $state = { counter: 0 };
function counter(  state: $state = initialState,  action: $action): $state {    switch (action.type) {    case INCREASE_COUNTER:      return Object.assign({}, state, {        counter: action.increment + state.counter      });        default:      return state;  }};

Установка определений библиотеки потока

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

npm install -g flow-typed
// Automatically download and install all relevant libdefsflow-typed install
// Orflow-typed install @ // e.g. redux@4.0.0

Определения библиотеки установлены в набранный поток Папка, которая позволяет потоку работать из коробки без какой-либо дополнительной конфигурации ( Детали ).

Тип Проверка состояния приложения

Раньше мы уже набрали состояние, как это:

type $state = {  +counter: number};

Пока это работает для простого примера, как то, как указано выше, он разрушается после того, как ваше состояние становится значительно большим. Вы должны были бы вручную редактировать Тип $ State Каждый раз, когда вы представляете новый редуктор или измените существующий. Вы также не хотели бы сохранить все ваши редукторы в одном файле. Вместо этого вы хотите сделать реконструкцию своих редукторов в отдельные модули и использовать redux Коммунатории

Так как в центре внимания этой статьи на Тип проверки Реакция/redux/red-redux приложение, а не на здании один, я собираюсь предположить, что вы знакомы с Коммунатории функция. Если нет, отправляйтесь на Учебник Redux чтобы узнать все об этом.

Предположим, мы вводим новую пару действий/редукторов в отдельном модуле:

// playSong.js
export const PLAY_SONG = 'PLAY_SONG';
// Typing the actionexport type $playSongAction = {  type: 'PLAY_SONG',  song: ?string};
// Typing the action creatorexport function playSong(song: ?string): $playSongAction {  return {    type: PLAY_SONG,    song: song  };};
// Typing arg1 and the return value of the reducer [*1]export type $song = ?string;
// Typing the state [*1]export type $songState = {  +song: $song};
// [*1][*2]const initialValue: $song = null;
// Typing the reducer [*1][*3]function song(  state: $song = initialValue,  action: $playSongAction): $song {    switch (action.type) {    case PLAY_SONG:      return action.song;        default:      return state;  }};

[* 1]: Если мы используем Коммунатории Функция, важно отметить, что Ваш редуктор больше не должен возвращать состояние, а скорее ценность к ключу в состоянии Отказ В связи с этим я думаю Учебник Redux Мне немного не хватает четкости, так как он не утверждает это явно, хотя это ясно из примерных фрагментов кода.

[* 2]: Редукторы не могут вернуть undefined поэтому мы должны согласиться на null Отказ

[* 3]: Поскольку редуктор больше не получают и возвращает состояние в форме {Песня: строка} , а скорее ценность к песня Ключ в объекте штата, нам нужно изменить типы его первого аргумента и возврата от $ Songstate к $ песня Отказ

Мы изменим и рефактору inwaresecounter также:

// increaseCounter.js
export const INCREASE_COUNTER = 'INCREASE_COUNTER';
export type $increaseCounterAction = {  type: 'INCREASE_COUNTER',  increment: number};
export function increaseCounter(by: number): $action {  return {    type: INCREASE_COUNTER,    increment: by  };};
export type $counter = number;
export type $counterState = {  +counter: $counter};
const initialValue: $counter = 0;
function counter(  state: $counter = initialValue,  action: $increaseCounterAction): $counter {    switch (action.type) {    case INCREASE_COUNTER:      return action.increment + state;        default:      return state;  }};

Теперь у нас есть 2 пары действия/редуктора.

Мы можем создать новый Государство Тип для хранения типа состояния нашего приложения:

export type State = $songState & $counterState;

Это поток Тип пересечения и эквивалентно:

export type State = {  song: $song,  counter: $counter};

Если вы не хотите создавать $ Songstate и $ CounterState Только для использования в наборе пересечения набрав состояние приложения Государство Это совершенно хорошо, – иди со вторым внедрением.

Тип Проверка магазина redux и отправка

Я обнаружил, что поток сообщил ошибки в моих контейнерах (в контексте контейнер/компонент Paradigm ).

Could not decide which case to select. Since case 3 [1] may work but if it doesn't case 6 [2] looks promising too. To fix add a type annotation to dispatch [3].

Это было в связи с моим mapdispatchtopops функция. Шкафы 3 и 6 следующие:

// flow-typed/npm/react-redux_v5.x.x.js
// Case 3declare export function connect<  Com: ComponentType<*>,  A,  S: Object,  DP: Object,  SP: Object,  RSP: Object,  RDP: Object,  CP: $Diff<$Diff;, RSP>, RDP>  >(  mapStateToProps: MapStateToProps,  mapDispatchToProps: MapDispatchToProps): (component: Com) => ComponentType;
// Case 6declare export function connect<  Com: ComponentType<*>,  S: Object,  SP: Object,  RSP: Object,  MDP: Object,  CP: $Diff, RSP>  >(  mapStateToProps: MapStateToProps,  mapDispatchToPRops: MDP): (component: Com) => ComponentType<$Diff & SP>;

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

Я не мог найти много документации по этому аспекту ввода приложения Redux/React-redux. Я узнал, погружение в либедефы и глядя на Исходный код для других проектов (хотя и демонстрационный проект). Если у вас есть какие-либо идеи, пожалуйста, дайте мне знать, чтобы я мог обновить этот пост (с правильной атрибуцией, конечно).

Тем временем я обнаружил, что это работает:

import type {  Store as ReduxStore,  Dispatch as ReduxDispatch} from 'redux';
// import any other variables and types you may need,// depending on how you organized your file structure.
// Reproduced from earlier onexport type State = {  song: $song,  counter: $counter};
export type Action =   | $playSongAction  | $increaseCounterAction
export type Store = ReduxStore;
export type Dispatch = ReduxDispatch;

Направляясь в ваши контейнерные модули, вы можете затем перейти к типу mapdispatchtopops Как следует: const mapdispatchtopons = (рассылка: рассылка) => {... };

Обертывание

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

Я не могу гарантировать, что руководство в этой статье следует наилучшими практиками, либо концептуально звучат, или даже на 100% правильно. Если вы обнаружите какие-либо ошибки или проблемы, пожалуйста, дайте мне знать!