Можно ли отправить действие в самом редукторе? У меня есть индикатор и аудио элемент. Цель состоит в том, чтобы обновить индикатор выполнения, когда время обновляется в аудиоэлементе. Но я не знаю, где разместить обработчик событий ontimeupdate или как отправить действие в обратный вызов ontimeupdate, чтобы обновить индикатор выполнения. Вот мой код:
//reducer
const initialState = {
audioElement: new AudioElement('test.mp3'),
progress: 0.0
}
initialState.audioElement.audio.ontimeupdate = () => {
console.log('progress', initialState.audioElement.currentTime/initialState.audioElement.duration);
//how to dispatch 'SET_PROGRESS_VALUE' now?
};
const audio = (state=initialState, action) => {
switch(action.type){
case 'SET_PROGRESS_VALUE':
return Object.assign({}, state, {progress: action.progress});
default: return state;
}
}
export default audio;
AudioElement
? Кажется, что это не должно быть что-то в состоянии.Ответы:
Распределение действия внутри редуктора является анти-паттерном . Ваш редуктор должен быть без побочных эффектов, просто переваривая полезную нагрузку действия и возвращая новый объект состояния. Добавление слушателей и диспетчеризация действий внутри редуктора могут привести к цепным действиям и другим побочным эффектам.
Похоже, ваш инициализированный
AudioElement
класс и слушатель событий находятся внутри компонента, а не в состоянии. В прослушивателе событий вы можете отправить действие, которое будет обновлятьсяprogress
в состоянии.Вы можете либо инициализировать
AudioElement
объект класса в новом компоненте React, либо просто преобразовать этот класс в компонент React.Обратите внимание, что
updateProgressAction
он автоматически переносится,dispatch
поэтому вам не нужно вызывать диспетчер напрямую.источник
MyAudioPlayer
компоненту из родительского контейнера, которыйconnect
редактируетсяreact-redux
. Проверьте, как сделать это сmapDispatchToProps
здесь: github.com/reactjs/react-redux/blob/master/docs/...updateProgressAction
определяется в вашем примере?redux-thunk
что отправляет действие из другого действия, а не редуктора. stackoverflow.com/questions/35411423/…Запуск другой диспетчеризации до того, как ваш редуктор закончен, является анти-паттерном , потому что состояние, которое вы получили в начале вашего редуктора, больше не будет текущим состоянием приложения после его завершения. Но планирование другой отправки изнутри редуктора НЕ является анти-паттерном . Фактически это то, что делает язык Elm, и, как вы знаете, Redux - это попытка перенести архитектуру Elm в JavaScript.
Вот промежуточное ПО, которое добавит свойство
asyncDispatch
всем вашим действиям. Когда ваш редуктор завершит работу иasyncDispatch
вернет новое состояние приложения, сработаетstore.dispatch
с любым действием, которое вы ему дадите.Теперь ваш редуктор может сделать это:
источник
dispatch
которые должны возвращать действие. Я изменил последние строки на:const res = next(actionWithAsyncDispatch); syncActivityFinished = true; flushQueue(); return res;
и это сработало отлично.Вы можете попробовать использовать такую библиотеку, как redux-saga . Это позволяет очень аккуратно упорядочить асинхронные функции, запустить действия, использовать задержки и многое другое. Это очень мощно!
источник
supplier
информации, когда пользователь пытается посетитьitem
страницу с подробностями. ВыcomponentDidMount()
бы выпалить функцию , которая отправляет действие, скажемFETCH_SUPPLIER
. Внутри редуктора вы можете отметить что-то вроде a,loading: true
чтобы показать счетчик во время выполнения запроса.redux-saga
будет прислушиваться к этому действию и в ответ запустить фактический запрос. Используя функции генератора, он может дождаться ответа и сбросить егоFETCH_SUPPLIER_SUCCEEDED
. Затем редуктор обновляет магазин информацией о поставщике.Reduce-loop берет реплику от Elm и предоставляет этот паттерн.
источник