Descargue un archivo programáticamente mientras brinda retroalimentación al usuario utilizando Redux.
Tengo un backend que devuelve un archivo para descargar.
Actualmente, cuando el usuario realiza una acción, se envía una acción que ejecuta el reductor “export” y realiza el truco habitual para descargar un archivo. Estoy usando redux-toolkit.
const mySlice = createSlice({
name: "my",
initialState,
reducers: {
export: (state) => {
const link = document.createElement("a")
link.href = '...';
document.body.appendChild(link)
link.click()
link.parentNode?.removeChild(link)
},
}
})
Y esto funciona. Sin embargo, me gustaría proporcionar un feedback al usuario mientras se está realizando la descarga, es decir, un diálogo modal. Así que he definido una propiedad “isExporting” en el estado, y hay un componente que muestra el diálogo dependiendo de esta propiedad.
Sin embargo, el reductor escrito de esta manera no funciona:
export: (state) => {
state.isExporting = true;
const link = document.createElement("a")
link.href = '...';
document.body.appendChild(link)
link.click()
link.parentNode?.removeChild(link)
state.isExporting = false;
}
porque creo que estoy introduciendo efectos secundarios, y además el estado se establecerá después de que se haya ejecutado el reductor y no en medio.
¿Cuál es la forma correcta de hacer esto?
davy.ai
La forma correcta de hacer esto es utilizar una acción asíncrona en redux-toolkit. Esto se puede lograr creando un creador de acciones adicional
exportAsync
tipo thunk que realiza la descarga del archivo, mientras se estableceisExporting
comotrue
antes de que comience la descarga y se vuelve a establecer comofalse
después de que la descarga se completa. Aquí tienes un ejemplo de cómo implementarlo:En el código anterior,
setIsExporting
es una acción síncrona normal que estableceisExporting
en el estado, yextraReducers
escucha las accionespending
yfulfilled
deexportAsync
(que serán despachadas automáticamente por el middleware thunk al invocarla). Cuando se despachaexportAsync.pending
,isExporting
se establece entrue
, y cuando se despachaexportAsync.fulfilled
(es decir, cuando se completa la descarga), se vuelve a establecer enfalse
.Para despachar
exportAsync
en un componente, simplemente impórtala e inclúyela como una propiedad o utilízala conuseDispatch()
, dependiendo de cómo estés utilizando Redux en tu aplicación:Ten en cuenta que este enfoque elimina la necesidad de la acción
export
en tu código original, ya que ahora está manejada completamente porexportAsync
.