Это единственное, для чего я еще не нашел стандартного решения.
У меня есть настройка магазина с redux-saga для обработки побочных эффектов, я отправляю действие (с асинхронными побочными эффектами) из компонента и теперь хочу, чтобы компонент что-то делал после обработки побочных эффектов (например, переход к другому маршруту / screen, всплывающее окно / всплывающее окно или что-то еще).
Также я хочу отображать индикатор загрузки или любые ошибки при сбое.
До redux этот вид потока был прямолинейным, он выглядел бы примерно так:
try {
this.setState({loading: true});
const result = await doSomeRequest();
this.setState({item: result, loading: false});
} catch (e) {
this.setState({loading: false, error: e});
}
С помощью redux я обычно хочу отправить действие, инициирующее поток, и иметь всю связанную информацию в магазине, чтобы многие компоненты могли слушать, что происходит.
У меня могло быть 3 действия: «запрошено», «успешно», «не удалось». В моем компоненте я бы отправил запрошенное действие. Ответственная сага затем отправит действие «успешно» или «не удалось» после обработки «запрошенного».
Мой компонент отразит изменения. Но стандартного способа узнать, завершилось ли действие, я не нашел. Возможно, магазин не обновился в результате асинхронного действия (NO-OP, но состояние загрузки все равно изменится, я думаю). Но действие все равно выполнено, и я хочу сделать что-то вроде перехода на другой экран.
Я действительно пытался найти такой (казалось бы, распространенный) сценарий в документах redux, redux-saga docs или Stackoverflow / Google, но безуспешно.
Примечание: также с redux-thunk я думаю, что этого поведения легко достичь, так как я могу просто. Затем при отправке асинхронного действия и получить действие успеха или действие ошибки в catch (исправьте меня, если я ошибаюсь, никогда реально использовал thunk). Но я еще не видел такого же поведения, достигнутого с помощью redux-saga.
Я придумал 3 конкретных решения:
Наиболее примитивное решение, обрабатывающее только «успешные» / «неудачные» действия компонента. Я не большой поклонник этого решения. В моей конкретной реализации нет действия, указывающего, что асинхронный запрос запущен. Побочные эффекты обрабатываются прямо в компоненте, а не абстрагируются внутри саги. Много потенциального повторения кода.
Запуск одноразовой саги прямо перед отправкой действия запроса, который сопоставляет действия "успех" / "сбой" друг с другом и позволяет реагировать на первое выполняющееся действие. Для этого я написал помощник, который абстрагирует ход саги: https://github.com/milanju/redux-post-handling-example/blob/master/src/watchNext.js Этот пример мне нравится намного больше, чем 1. поскольку он простой и декларативный. Хотя я не знаю, имеет ли создание саги во время выполнения, подобное этой, какие-либо негативные последствия, или, может быть, есть другой «правильный» способ добиться того, что я делаю с помощью redux-saga?
Помещение всего, что связано с действием (загрузка, успешный флаг, ошибка), в хранилище и реакция в componentWillReceiveProps на изменения действия ((! This.props.success && nextProps.success)) означает, что действие выполнено успешно). Это похоже на второй пример, но работает с любым выбранным вами решением для обработки побочных эффектов. Может быть, я наблюдаю за чем-то вроде обнаружения неработающего действия, если реквизиты появляются очень быстро, а реквизиты, входящие в componentWillReceiveProps, будут `` накапливаться '', а компонент вообще пропускает переход от неуспеха к успеху?
Не стесняйтесь взглянуть на пример проекта, который я создал для этого вопроса, в котором реализованы полные примеры решений: https://github.com/milanju/redux-post-handling-example
Я хотел бы получить информацию о методах, которые я использую для обработки описанного потока действий.
- Я что-то не понимаю? «Решения», которые я придумал, были для меня непростыми. Может, я смотрю на проблему не с той стороны.
- Есть ли проблемы с приведенными выше примерами?
- Есть ли лучшие практики или стандартные решения этой проблемы?
- Как вы справляетесь с описанным потоком?
Спасибо за прочтение.