Digamos que estoy construyendo un reproductor de audio que consta de un panel de control, donde el usuario puede pausar/reproducir la pista seleccionada actualmente y los propios reproductores de audio. Las acciones posibles son pausar/reproducir la pista, y el componente del reproductor de audio escucha los cambios de estado y decide si reproducir/pausar la pista (código de ejemplo tomado de https://stackoverflow.com/a/50880480/18547676 )
Actions: // plays active track export const playTrack () => ({ type: 'musicPlayer/PLAY_TRACK', payload: true, }); // pauses active track export const pauseTrack () => ({ type: 'musicPlayer/PLAY_TRACK', payload: false, }); Reducer: const initialState = { isPlaying: false, }; export const musicPlayer = (state = initialState, action) => { switch (action.type) { case 'musicPlayer/PLAY_TRACK': return { ...state, isPlaying: action.payload, } default: return state } } Component (state mapped to props): componentDidUpdate() { if(this.props.audioTrack) { // What to do in case audioTrack.play() errors out? if(this.props.isPlaying) audioTrack.play(); else audioTrack.pause(); } }Mi pregunta es la siguiente; ¿Cuál es la forma recomendada de manejar los casos en los que, por ejemplo, el reproductor de audio no pudo ejecutar la acción debido a un error? Por ejemplo, el usuario quería pausar el reproductor actual; el estado cambió y el reproductor de audio recibió la actualización, pero no pudo realizar la acción debido a un error (en cuyo caso, el estado de Redux y el estado real del reproductor no están sincronizados). ¿Hay algún patrón para manejar esto?
Depende del reproductor de audio real que estés usando. El navegador nativo, por ejemplo, tiene la opción de adjuntar detectores de eventos: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/onerror
Puede usar esto para sincronizar el estado de error con redux:
audioElem.onerror = () => { dispatch(setError(audioElem.error); };La idea general sería que si la interfaz de audio emite eventos, envíe acciones de reducción. Y la interacción del usuario, como presionar un botón de reproducción, envía acciones que llaman a métodos en la interfaz de audio como un efecto secundario (ejemplo usando middleware thunk):
const playAction = () => async (dispatch, getState) => { dispatch(playRequested()); try { await audioElem.play(); dispatch(playStarted()); } catch (error) { dispatch(playFailed(error)); } };