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

Дорога до redux и обратно

Почему я решил вернуться в Vanilla Reacti, сделал какой-то прототип работать, чтобы продемонстрировать преимущества уровня доступа к данным между логикой клиента и настойчивостью. По пути я стал большим поклонником графаql. Хотя я люблю реагировать, это не было низкой (ER) -Code

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

Почему я решил вернуться к реагированию ванили

Я сделал несколько прототипов работы, чтобы продемонстрировать преимущества уровня доступа к данным между клиентской логикой и настойчивостью. По пути я стал большим поклонником графаql. Хотя мне нравится реагировать, это не было никакой низкой (ER) -Code, который я надеялся, что это будет (хотя, эй: нет jQuery!). Я попробовал смешивание в Redux, чтобы упростить кодирование дальше, но там были разочарованные.

Реагируйте концептуально просто: компонент может содержать Государство и получить реквизит Отказ Реагирование будет мониторировать изменения в состоянии и восстановит этот компонент и Любые дочерние компоненты Это может быть затронуто государственным изменением. Состояние передается детям, хотя реквизиты (атрибуты элемента). Некоторые встроенные методы реактивных компонентов вызываются в процессе, каждый из которых может быть переопределен по мере необходимости (чтобы избежать, скажем, ненужные повторные рендеры).

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

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

При изучении реагирования, это помогает сделать четкое различие между презентационные компоненты и Контейнерные компоненты Отказ Председательные компоненты – это элементы, показанные на странице. Контейнеры являются компонентами, которые поддерживают состояние для их дочерних компонентов. Компоненты контейнеров могут быть презентационными, контейнерами или оба. Контейнеры умны и имеют государственную логику. Компоненты презентации глупы и в основном шаблоны HTML, которые обрабатывают презентацию прошедших в реквизитах.

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

Реквизит, реквизит и больше реквизит

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

Давайте возьмем пример из собственных документов React:

function Welcome(props) {
  return 

Hello, {props.name}

; } function App() { return (
); }

Добро пожаловать Компонент принимает набор свойств или реквизитов. Он использует опоры под названием Имя Чтобы отобразить персонализированное приветственное сообщение. Содержащий компонент является анонимным

. Это проходит имена в Добро пожаловать компонент для трех человек.

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

function Welcome(props) {
  return 

Hello, {props.first_name} {props.last_name}

  • email: {props.email}
  • phone: {props.phone}
  • address: /* mercifully omitted */
; } function App() { return (
); }

Явно проходящие реквизиты шумные. Более того, если приветственный компонент является составным компонентом нескольких других компонентов, каждый из которых со своим собственным набором необходимых свойств, вы должны пройти теми к приветственному компоненту.

Реквисы – это не только данные, но и методы. Реквизиты – это неизменный условно.

Если любой ребенок хочет изменить свойство, оно должно быть сделано через пропущенную установочный метод из некоторого контейнера, который удерживает состояние. Ребенок вызывает метод состояния Set, обновляет состояние и генерирует новые значения опоры. Затем каждый ребенок уведомлен о изменениях имущества. Ребенок, который делает мутацию государства, не знает, какой контейнер удерживает состояние, но не нужно. Это вызывает набор метод, который он дан из некоторого анонимного родительского контейнера.

Вот еще один пример из реагирования документов:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
      
// This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }
    
handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }
    
render() {
    return (
      
    );
  }
}

ReactDOM.render(
  ,
  document.getElementById('root')
);

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

handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

render() => ;

ReactDOM.render(
  ,
  document.getElementById('root')
);

Arrggh, рефакторинг

Таким образом, вы делаете все это распространение свойства через все детские компоненты и все прекрасно. Затем вы добавляете еще один компонент и осознаете, что он зависит от некоторого состояния, который не находится в контейнере, который вы хотите поставить новый компонент в.

Давайте начнем с простого списка и деталей приложения:

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

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

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

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

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

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

Несущая вода

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

Решение 1: redux

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

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

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

Так вот где приходит redux. Он предоставляет все компоненты только с одним состоянием, поддерживаемым независимо от, но доступными для всех компонентов реагирования.

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

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import RootReducer from './app/reducers'
import App from './app/app'

const store = createStore(RootReducer)

ReactDOM.render(
  
    
  ,
  document.getElementById('root')
)

Другие две части немного больше участвуют: действия и редукторы. Событие, такое как результат нажатия на Keystroke или базе данных, создает действие. Затем действие отправляется для обработки некоторыми Resolver на основе типа действий. Если вы читаете Моя предыдущая серия На Microsevices Seneca вы заметите, как действия Redux аналогичны шаблонам Seneca, и редукторы аналогичны действиям Seneca.

Редукторы, когда-то срабатывают, изменит состояние Redux в соответствии с данными в действии. Таким образом, компонент может охватить действие, которое может вызвать запрос базы данных или файловой выбор или что-то еще, результаты которых прикреплены к действию в качестве полезной нагрузки, а затем отправляются в облако редукторов, один из которых будет (надеюсь) забрать Действие влево и измените часть состояния, чтобы компоненты, слушающие части у него, имеют возможность повторно представить.

Нет прохождения реквизит от контейнеров для детей, но реквизиты все еще вовлечены.

import { connect } from 'react-redux'
import { setVisibility } from '../actions'
import Popup from '../components/Popup'
const mapStateToProps = (state, ownProps) => {
  return {
    active: ownProps.toggle === state.visibilityToggle
  }
}
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onClick: () => {
      dispatch(setVisibility(ownProps.toggle))
    }
  }
}
const Toggle = connect(
  mapStateToProps,
  mapDispatchToProps
)(Popup)
export default Toggle

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

Традиционный способ, которым это организовано, это то, что у вас есть действия в /Действия папка. Обычно в этой папке есть index.js. Редукторы в /Редукторы папка. Компоненты в /Компоненты папка или разделение между «презентацией» /Компоненты и /Контейнеры. И приложение будет в корневой папке.

Все это проводка, хотя

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

Это все очень хорошо и хорошо, пока вы не начните строить компоненты и вещи не работают правильно, и вам интересно, как:

  • Я не помнил, чтобы определить действие?
  • Я не помнил, чтобы экспортировать действие?
  • Я определил редуктор?
  • Я включил постоянную действие в моем компоненте?
  • Я импортировал его в мой редуктор?
  • Я сделал опечатка?
  • Как было название этого файла, который имел эту вещь, которую я сейчас забыл?

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

Решение 2: Вернуться к реакции с ES6

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

Распространение и отдых

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

Используя оператор распространения объекта , можно пропустить свойства наряду с детьми без явного ссылки на сами свойства. Хотя это все еще «несет воду» из контейнера к подкомпонентам, он делает это неявно. Весь контейнер знает, у него есть реквизиты для отправки. Если у него есть государство, он тоже отправляет их.

Следует упомянуть, однако, что оператор спреда для объектов еще не является официальной частью ECMAScript. Transpiler Babel поддерживает его, если он настроен на это.

{
 "presets": [
  "latest",
  "react"
 ],
 "plugins": ["transform-object-rest-spread", "syntax-object-rest-spread"]
}

Выбор свойств

Одной из проблем является прохождение слишком большой информации до детских компонентов. Один из способов избежать то, что для более высоких контейнеров и компонентов «выключить» свойства, которые они заинтересованы, и только передают остальные. Это можно сделать с помощью деструкурирования объекта:

var { checked, ...other } = props;

Здесь, проверяемое опор вытащено из других реквизитов, а потом другой передается (без проверки [пример от ссылка выше]):

function FancyCheckbox(props) {
  var { checked, ...other } = props;
  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
  // `other` contains { onClick: console.log } but not the checked property
  return (
    
); }

Реагировать или redux?

При создании прототипа для демонстрации некоторой концепции или функции проще лучше. Реагируйте концептуально легче иметь дело с. Redux многое происходит под капотом, и было отмечено, насколько мелкозернистые действия могут стать. Нужно показать спиннер? Окружил действие!).

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