Redux: Серия скринкастов Redux на Egghead

Созданный на 24 нояб. 2015  ·  69Комментарии  ·  Источник: reduxjs/redux

Если вы следите за репозиторием Redux, но еще не погрузились в него или не понимаете некоторые из его фундаментальных аспектов, вы будете рады узнать, что Egghead только что опубликовал мою серию «Начало работы с Redux» .

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

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

feedback wanted

Самый полезный комментарий

@markerikson спасибо, что

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

Ваш слой пользовательского интерфейса просто связывает взаимодействие пользователя с обработчиками. Когда кто-то нажимает кнопку, ваш пользовательский интерфейс настроен на вызов _some_ handler. Часто компонент получает эти обработчики как свойства — например, создатель связанного действия. Пользовательский интерфейс не знает, что происходит, когда он вызывает обработчик — он просто вызывает его.

Для слоя пользовательского интерфейса не имеет значения, отправляет ли «обработчик» функцию (для обработки промежуточным программным обеспечением) или выполняет ли он асинхронный вызов, а _затем_ отправляет обычное действие — пользовательский интерфейс полностью независим (или, по крайней мере, он _может_ быть агностиком)

Большая часть вашего «приложения» находится в этих «обработчиках», независимо от того, используете ли вы переходники или нет. В типичном приложении реакции/редукции эти «обработчики» часто являются своего рода создателями действий. Вы можете написать все свои асинхронные вещи как преобразователи и отправить их. Или вы можете написать все свои асинхронные вещи как функции, которые принимают dispatch в качестве аргумента. С точки зрения компонента это либо someHandler(dispatch) ИЛИ dispatch(someHandler()) , либо в случае создателей связанных действий, переданных сверху, это просто someHandler() в обоих случаях. Вы можете создать версию bindActionCreators которая полностью скроет это отличие от слоя пользовательского интерфейса.

Если вы дадите мне реагирующее/редукционное приложение, написанное с помощью создателей действий, использующих redux-thunk, я могу полностью заменить redux-thunk и использовать подход без промежуточного программного обеспечения без фундаментального изменения какого-либо слоя пользовательского интерфейса. (примечание: я умалчиваю о том, где/как вы вводите getState , но я _верю_, что это незначительная деталь).

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

Я ценю обсуждение, и я надеюсь, что я не сталкиваюсь с негативом.

Все 69 Комментарий

:+1:

  1. Состояние локального компонента и глобальное состояние
  2. Действие, обрабатываемое несколькими редьюсерами, по сравнению с отношением «действие-редуктор 1 к 1»
  3. Обработка цепочек действий (особенно асинхронных), когда второе действие должно запускаться сразу после завершения первого.
  4. Методы оптимизации для предотвращения ненужного повторного использования (пакетные действия, повторный выбор и т. д.).

:+1:

Я только что посмотрел первые 16 эпизодов сериала и думаю, что это отличный ресурс, который мы, вероятно, будем использовать для внутреннего обучения в компании, в которой я работаю. Однако тот факт, что вы когда-либо использовали только простые объекты и глубокую заморозку для своего дерева состояний, и никогда не использовали или не ссылались на неизменяемые библиотеки, такие как immutable-js, заставляет меня задуматься, поощряете ли вы людей идти по этому пути, или это просто делает представление идеи проще?

Было бы здорово узнать ваши мысли по этому поводу.

Добавление Immutable в смесь может сбить с толку новичков, которым нужно научиться различать Redux и Immutable API, которые могут предположить, что требуется Immutable и т. д. Тем не менее, это хорошая идея для пары продвинутых уроков!

Добавление Immutable в смесь может сбить с толку новичков, которым нужно научиться различать Redux и Immutable API, которые могут предположить, что требуется Immutable и т. д. Тем не менее, это хорошая идея для пары продвинутых уроков!

Хорошо, имеет смысл. Просто приятно знать, что вы думаете об этом решении :-).

Что сказал @smashercosmo :+1:

Модульное тестирование. ТДД.

Что сказал @cateland :+1:

Должен сказать, что я очень впечатлен вашими навыками, способными таким образом создавать отличные js-библиотеки с обширной документацией и краткими учебными пособиями.

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

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

Замечательно сделано, так держать! :)

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

Это очень хорошо.

Пункт 3 в списке @smashercosmo — это то, что я тоже хотел бы знать.

что сказал @wpannell ! Модульное тестирование/TDD!

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

Что конкретно вас интересует в отношении модульного тестирования?
Уроки 5, 11, 12 дают представление о том, как тестировать редукторы.

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

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

Во-первых, отличные видео. Уже понимаю сокращение, но это было освежающе.
Если вы создаете более продвинутые видео, могу ли я предложить асинхронные действия/промежуточное ПО.
Не думайте, что модульное тестирование действительно нуждается в каком-либо покрытии. Вы можете просто вызвать свои функции редуктора и утвердить их?

Да, я думаю, это не что иное, как обертывание expect в тестах мокко. :пальцы вверх:

Благо все так просто!

Неизменяемость с хэшами идентификаторов объектов (например, [post._id]: {...post} ).

Я обнаружил, что слишком сильно полагаюсь на функцию reduce чтобы взять массив объектов API и создать с его помощью хэш идентификатора. Я знаю, что normalizr справится с некоторыми из них, но я хотел бы видео, похожие на видео EggheadIO, где вы ведете нас из точки А в точку Б. Это не только вещь, основанная на Redux, но и сильно переплетенная.

@raquelxmoss

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

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

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

Я также хотел бы усовершенствованный состав редуктора.

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

Смотрел все, очень хорошо! Мне понравилось использование синтаксиса ES6/7 (подобно Object.assign ), функциональных компонентов React 0.14 и отказ от неизменяемых вещей.

Возможно, видео, объясняющее рекомендуемую архитектуру кода.

И обновить документ, чтобы использовать синтаксис ES6/7? (приветствуется ли пиар в этом направлении?)

Модульное тестирование, создание промежуточного программного обеспечения API, выполнение OAuth/аутентификации пользователя с помощью Redux, использование Immutable с Redux (как его настроить, лучшие практики и т. д.)

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

@gaearon Что вы думаете о структурировании действий в примерах видео как стандартного { type: string, payload: Object } с самого начала? Я говорю о примере со списком счетчиков, где полезная нагрузка помещается в сам объект действия; { type: string, index: number } . Мне это кажется антипаттерном.

Что вы думаете о структурировании действий в примерах видео как стандартного { type: string, payload: Object } с самого начала? Я говорю о примере со списком счетчиков, где полезная нагрузка помещается в сам объект действия; {тип: строка, индекс: число}. Мне это кажется антипаттерном.

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

Раньше люди думали о payload , source в исходной документации Flux всякими волшебными вещами. Они слепо копировали эти вещи, не понимая, зачем они существуют и тщательно оценивая, нужны ли они им вообще. Позже они жаловались на то, что Flux сложный и многословный, хотя на самом деле во многих случаях они сами копировали многословные (но несущественные) части.

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

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

@сомпиласар

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

Кроме того, нет абсолютно ничего неструктурированного в том, чтобы не следовать FSA. { type: 'STUFF', id: 1 } по своей сути не хуже, чем { type: 'STUFF', payload: { id: 1 } } . Это просто вопрос вкуса и (иногда) соглашения об инструментах. Сохранение объектов действия на payload меньше не усложняет работу с ними.

У нас есть несколько уроков по юнит-тестированию Redux, которые скоро выйдут на Egghead 😄

Мы отложили ЛЮБЫЕ уроки Redux на какое-то время, чтобы у Дэна был первый шанс. Полностью стоит ожидания, а затем некоторые.

«Создание приложения с помощью Idiomatic Redux» был бы прекрасным курсом для продвинутых пользователей 👍

@joelhooks оба звучат потрясающе!

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

@kevinrenskers это не видеоряд, но если вы чувствуете , как рассекает что - то, там находятся несколько действительно отличный пример Макеты вы можете ссылаться!

Те, кто попросил структуру проекта для примера Дэна и конфигурации Webpack.

Пожалуйста, проверьте это https://github.com/urbanvikingr/todo.

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

Мой список пожеланий к видео Egghead.io:
тестирование действия / редуктора с Jasmine
глубокое погружение в промежуточное ПО (thunk/promises)

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

@grigio Вас может заинтересовать это обсуждение https://github.com/rackt/redux/issues/1145 о маршрутизации

@urbanvikingr спасибо, подписался. Опрос кажется закрытым, но я бы проголосовал под номером 1168.

Уроки на самом деле довольно хорошие, но отвлекает то, что когда вы говорите «магазин», это звучит как «муторная работа».

Здесь все это заметили и отвлеклись. Они просто слишком политкорректны, чтобы поднимать эту тему. Так что да, я решил быть _тем_ парнем, на случай, если никто другой никогда этого не сделает :)

Со временем я стану лучше говорить по-английски. Пока это лучшее, что я могу сделать ;-)

@gaearon Вы чертовски хорошо объяснили Redux. Престижность вам и вашим достижениям в области открытого исходного кода.

Удивительный набор уроков. Мне особенно понравилось, как вы повторно реализовали каждую из основных функций Redux с нуля, «читая исходный код». Поддерживаю кого-то еще, кто был впечатлен тем, насколько понятны учебные пособия и вся документация для Redux. До сих пор, когда кто-то наверстывает упущенное за два года развития внешнего интерфейса, мне было трудно усвоить концепции, но документы были удивительно полезны в этом. Так держать, и спасибо!

(Также не слушайте @jugimaster , не все были отвлечены вашим акцентом и были «слишком политкорректны, чтобы упоминать об этом», или даже заботились о том, чтобы у вас был акцент.)

@ianstormtaylor
Это не акцент, кстати :)

Мне тоже было все равно, но я точно отвлекся!

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

Привет @gaearon ,

Безумно понравился ваш курс. Хорошо сделано! Это было очень полезно.

Я добавил три видеоурока по тестированию Redux в свой недавний курс Egghead:
https://egghead.io/series/react-testing-cookbook

Я надеюсь, что они будут комплиментарными ко всей той замечательной работе, которую вы проделали!

Солидный курс!

Улучшает не только знания Redux, но и знания современных практик в целом! Продолжай в том же духе :+1: :tada:

эй, только что понял, что в видео нет ссылки/ссылки на код. Может быть, очевидно, и, возможно, достаточно простые пользователи могут просто скопировать видео; но я думаю, что многие люди могли бы извлечь пользу из репозиториев с точным кодом в видео - почему бы и нет?

Фрагменты кода для каждого урока доступны подписчикам Egghead. :-)
Видео бесплатные, но платформа должна зарабатывать деньги, чтобы инвестировать в новые курсы, отправлять оборудование инструкторам, размещать видео, улучшать веб-сайт и так далее.

Тем не менее, у нас есть папка examples/todos которая в значительной степени соответствует курсу.

... круто, я скучаю по нему тогда? Ищу ссылку(и)...

@gaearon извиняется, только что пересмотрел видео. код прямо здесь :)... посмотрел видео, купил членство, посмотрел другие... только что вернулся к видео с редуксом, на самом деле залогинился. ура.

Кстати, несколько человек жаловались на то, что стенограммы неточны.
Пожалуйста, отправьте PR, чтобы исправить их: https://github.com/eggheadio/egghead-redux-transcripts

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

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

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

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

Вот пример кода:

/* actions.js */
// ...
export const USER_MOVE_COLUMN = 'USER_MOVE_COLUMN'

export function userMoveColumn (columnIndex, moveToIndex) {
  return {
    type: USER_MOVE_COLUMN,
    columnIndex,
    moveToIndex
  }
}

export const DATA_TABLE_MOVE_COLUMN = 'DATA_TABLE_MOVE_COLUMN'
// ...

/* reducers.js */
// ...
export default function user (state=userInitialState, action) {
  switch (action.type) {
    // ...
    case USER_MOVE_COLUMN:
      return dataTable(state, assign(
        action,
        {type: DATA_TABLE_MOVE_COLUMN}
      ))
    // ...
    default:
      return state
  }
}
// ...
export default function dataTable (
  state=dataTableInitialState,
  action,
  key='dataTable')
{
  switch (action.type) {
    // ...
    case DATA_TABLE_MOVE_COLUMN:
      return {
        ...state,
        [key]: {
          ...state[key],
          columns: move(
            state[key].columns, action.columnIndex, action.moveToIndex
          )
        }
      }
    // ...
    default:
      return state
  }
}

Итак, вы можете видеть, что я создал зависимость между таблицей и хранилищем «модели», которой у меня не должно быть (хранилище модели должно использовать ключ коллекции для своего массива объектов). И dataTable манипулирует состоянием «родительского» редуктора, чего не должно быть. Мне пришло в голову, что мне нужно использовать там селектор, но в то время, когда я писал это, я пытался избежать дублирования большого хранилища только для того, чтобы изменить то, что было видно в пользовательском интерфейсе.

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

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

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

Спасибо за предупреждение :)

Интеграция redux-devtools в мой проект была для меня огромной болью. Я читал PR, где вы описываете, когда что использовать ... но я так запутался, что там так много всего, хмр, transform 3, redux hot reloader отличается от react hot reloader и так далее ..

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

@granteagon Разве эта пара редукторов не

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

@gaearon @markerikson Это пара редукторов для создателей действий. Однако в 90% случаев это нормально или даже желательно. Остальные 10% времени вы все еще можете использовать метод ручного кодирования. Я подумаю о том, что вы сказали, и учту это для будущего развития.

@granteagon @gaearon

Используя локальную абстракцию, похожую на reduxr, я бы сказал, что здесь нет дополнительной связи. Ничто не навязывает сопоставление 1:1 между действиями и редьюсерами. У вас все еще может быть два редюсера в двух разных слайсах, слушающих одно и то же действие:

const counterReducersA = {
  // this counter increments by 1 each time
  increment: (state, action) => state + 1
}

const counterReducersB = {
  // this counter increments by 2 each time
  increment: (state, action) => state + 2
}

const counterA = reduxr(counterReducersA, 0);
const counterB = reduxr(counterReducersB, 0);

const rootReducer = combineReducers({
  counterA: counterA.reducer,
  counterB: counterB.reducer
});

store.dispatch(counterA.action.increment());  // increments both counters

Конечно, если у вас есть более одной функции «редуктор», названной одной и той же вещью (то есть отвечающей на одно и то же действие), неявно обе они должны «ожидать», что полезная нагрузка действия будет иметь определенную форму --- что полностью аналогично иметь два редуктора в vanilla redux, оба обрабатывают одну и ту же константу type --- оба должны ожидать одинаковую форму действия.

Возможно, я неправильно понял, что ты имеешь в виду под связью, @gaearon ?

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

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

@battaile : это потому, что это правда :) Без промежуточного программного обеспечения любая асинхронность должна происходить полностью за пределами Redux (то есть, скорее всего, на уровне вашего пользовательского интерфейса, например, в компонентах React). Каждый раз, когда вы вызываете store.dispatch , действие будет идти прямо к функции редуктора, не передавать Go, не собирать 200 долларов, не делать никаких остановок по пути для вызовов AJAX.

Усилители магазина позволяют вам обернуть такие функции, как dispatch вашей собственной версией, и поэтому applyMiddleware обеспечивает абстракцию «конвейера промежуточного программного обеспечения», прежде чем что-то достигнет функции dispatch реального магазина. . По сути, это обеспечивает лазейку, из которой вы можете выскочить и делать любые асинхронные вещи, которые вы хотите, _внутри_ стандартного потока Redux.

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

потому что это правда :)

Я не сказал, что это ложь, я сказал, что это сбило меня с пути :)

Я просто хотел сделать что-то вроде следующего, что, казалось, означало, что я не мог:

const mapDispatchToProps = (dispatch) => ({
  onclick(searchTerm) {
    dispatch(actions.requestOrders(searchTerm));

    return fetch('http://localhost:49984/Order/Search?search=' + searchTerm)
      .then(response => response.json()).then(response => {
        dispatch(actions.receiveOrders(searchTerm, response));
      })
      .catch((err) => {
        dispatch(actions.receiveOrdersError('An error occurred during search: ' + err.message));
      });
  },
});

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

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

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

Да, разница в том, что асинхронное поведение технически происходит больше на уровне компонентов, а не «внутри» dispatch . Небольшое различие, но действительное.

Я не думаю, что кто-то на самом деле утверждает, что это утверждение технически неверно.

@markerikson Просто любопытно, есть ли у вас конкретные примеры, где имеет значение различие между внутренним и внешним?

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

Ммм... не уверен конкретно в "конкретных" примерах. В целом, различие между "внешним" и "внутренним" сводится к тому, происходит ли это _до_ того, как вы вызываете dispatch в первый раз, или _после_. Если это «снаружи» и «до», то вся ваша асинхронность и логика больше завязаны на слой представления, будь то React, Angular или что-то еще. Если "внутри" и "после", то у вас асинхронность и логика на уровне хранилища, а _не_ привязана к слою представления.

На самом деле это большая часть того, что я только что пытался сделать сегодня в обсуждении на Reddit: https://www.reddit.com/r/reactjs/comments/4spbip/has_anyone_inserted_a_controllerpresenter_layer/ .

Вопрос «какие действия я отправляю и когда я их отправляю?» является основной частью вашей бизнес-логики, а другая половина — «как мне обновить свое состояние в ответ на эти действия?». Если управление действиями находится в thunks, сагах и тому подобном, то действительно не имеет значения, был ли этот код запущен компонентом React, контроллером Angular, обработчиком кликов jQuery, экземпляром компонента Vue или чем-то еще. Ваша основная логика находится за пределами уровня пользовательского интерфейса, а уровень пользовательского интерфейса на самом деле просто отвечает за извлечение необходимых данных из хранилища, их отображение и преобразование пользовательских входных данных в вызов логической функции приложения.

Итак, в этом смысле я бы сказал, что вопрос «внутри» и «снаружи» имеет значение, потому что это концептуальное различие между тем, живет ли ваша логика на уровне приложения или на уровне пользовательского интерфейса.

@markerikson спасибо, что

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

Ваш слой пользовательского интерфейса просто связывает взаимодействие пользователя с обработчиками. Когда кто-то нажимает кнопку, ваш пользовательский интерфейс настроен на вызов _some_ handler. Часто компонент получает эти обработчики как свойства — например, создатель связанного действия. Пользовательский интерфейс не знает, что происходит, когда он вызывает обработчик — он просто вызывает его.

Для слоя пользовательского интерфейса не имеет значения, отправляет ли «обработчик» функцию (для обработки промежуточным программным обеспечением) или выполняет ли он асинхронный вызов, а _затем_ отправляет обычное действие — пользовательский интерфейс полностью независим (или, по крайней мере, он _может_ быть агностиком)

Большая часть вашего «приложения» находится в этих «обработчиках», независимо от того, используете ли вы переходники или нет. В типичном приложении реакции/редукции эти «обработчики» часто являются своего рода создателями действий. Вы можете написать все свои асинхронные вещи как преобразователи и отправить их. Или вы можете написать все свои асинхронные вещи как функции, которые принимают dispatch в качестве аргумента. С точки зрения компонента это либо someHandler(dispatch) ИЛИ dispatch(someHandler()) , либо в случае создателей связанных действий, переданных сверху, это просто someHandler() в обоих случаях. Вы можете создать версию bindActionCreators которая полностью скроет это отличие от слоя пользовательского интерфейса.

Если вы дадите мне реагирующее/редукционное приложение, написанное с помощью создателей действий, использующих redux-thunk, я могу полностью заменить redux-thunk и использовать подход без промежуточного программного обеспечения без фундаментального изменения какого-либо слоя пользовательского интерфейса. (примечание: я умалчиваю о том, где/как вы вводите getState , но я _верю_, что это незначительная деталь).

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

Я ценю обсуждение, и я надеюсь, что я не сталкиваюсь с негативом.

Этот курс великолепен. Закрытие этого, чтобы люди могли направить свои комментарии в репозиторий заметок сообщества для курса: https://github.com/tayiorbeii/egghead.io_redux_course_notes

Кроме того, обязательно посмотрите следующую серию, которую Дэн собрал вместе! https://egghead.io/courses/building-react-applications-with-idiomatic-redux

Была ли эта страница полезной?
0 / 5 - 0 рейтинги