es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo despachar una acción cuando cambia un estado en redux toolkit sin usar useEffect?

Si quiero despachar una acción cada vez que cambia un trozo de estado, actualmente lo hago escuchando ese estado dentro del gancho useEffect de un componente y despachando una acción cada vez que ese estado cambia.

Por ejemplo, digamos que tengo el siguiente trozo de código:

export const updateBar = createAsyncThunk("mySlice/updateBar", async () => {
  const { data } = await axios.get("/some/api");
  return data;
});

const mySlice = createSlice({
  name: "mySlice",
  initialState: {
    foo: false,
    bar: 0,
  },
  reducers: {
    updateFoo: (state, { payload }) => {
      state.foo = payload;
    },
  },
  extraReducers: {
    [updateBar.fulfilled]: (state, { payload }) => {
      state.bar = payload;
    },
  },
});

Ahora, si quiero actualizar "bar" cada vez que "foo" cambie, debo ir al lado del componente para agregar el siguiente código:
const Component = () => {
  const foo = useSelector((state) => state.mySlice.foo);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(updateBar());
  }, [dispatch, foo]);

  return <div></div>;
};

Me pregunto si es posible llamar a updateBar cada vez que foo cambie dentro del trozo de Redux y sin tener que tocar el lado del componente, porque creo que sería más limpio si todos los efectos secundarios del estado están abstraídos del componente.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible llamar a updateBar cada vez que cambie foo dentro de la porción de redux sin tener que modificar el lado del componente utilizando el método extraReducers de la función createSlice.

    Al modificar el código de ejemplo proporcionado anteriormente, podemos lograr este efecto:

    const mySlice = createSlice({
      name: "mySlice",
      initialState: {
        foo: false,
        bar: 0,
      },
      reducers: {
        updateFoo: (state, { payload }) => {
          state.foo = payload;
        },
      },
      extraReducers: (builder) => {
        builder.addCase(
          mySlice.actions.updateFoo,
          (state, action) => {
            updateBar().then((result) => {
              state.bar = result;
            });
          }
        );
      },
    });
    

    Aquí estamos utilizando builder.addCase() para escuchar la acción mySlice.actions.updateFoo, que cambia el estado de foo, y luego despachamos updateBar de forma asíncrona para actualizar el estado de bar.

    Este enfoque asegura que todos los efectos secundarios del estado se abstraigan del componente, como se solicita.

Comments are closed.