React note #14

Yechan Jeon·2021년 12월 29일
0

React dev

목록 보기
13/18
post-thumbnail

Advanced Redux


Side Effects, Async Tasks with Redux

Originally, Redux reducer functions is pure, side-effect free, synchronous.
Then Where should side-effects and async tasks be executed?
1. Inside the components (e.g useEffect hook)
2. Inside the action creaters

Frontend code depends on Backend code. If Backend does a lot of work, Frontend just send and recive data, use response data. However, If backend has lean functions, Frontend transform data and send data.

We don't have any backend function right now, so let's guess that frontend should do more works.

Where to put side-effect or async logic

  1. In component
    First of all, you should not mutate state outside of reducer function.
    To copy logic from reducer function and manipulate state values to send request, you should create new object from current object like this:
    const updatedItems = cart.items.slice() <- this will create new object which is not related to redux state.

Actually Writing this kind of code in component needs duplication or external function module when you need it in other places.
Also, This is not goal of using redux. If you transform data in component, redux just handling state change, not complex actions.
Therefore, you can consider write this logic differently.

let isInitial = true;

function App() {
  const dispatch = useDispatch();
  const showCart = useSelector((state) => state.ui.cartIsVisible);
  const cart = useSelector((state) => state.cart);

  useEffect(() => {
    const sendData = async () => {
     
      const response = await fetch(
        "https://react-http-975ab-default-rtdb.firebaseio.com/cart.json",
        {
          method: "PUT",
          body: JSON.stringify(cart),
        }
      );
      if (!response.ok) {
        throw new Error("Failed!");
      }
    };

    if (isInitial) {
      isInitial = false;
      return;
    }
    });
  }, [cart, dispatch]);

  return (
  // something
  );
}

In App.js (It doesn't need to be app.js), I'm using useEffect() to send http request. This is exactly what we wanted .
With dependencies 'cart', whenever cart updated, our http request function will send request to backend.
The reason i set 'isInitial' is to prevent initial execution because useEffect will be executed when app executed.

  1. In action creators
    We will create "Thunk"
    Thunk is a function that delays an action( action creator function doesn't return the action itself but return another function which eventually returns the action)
    Action creator -> return -> a function -> return -> action
    This is same process of creating action from redux toolkit
    export const cartActions = cartSlice.actions;

When you use redux toolkit, The good this is there is built-in transformation of actions.
Event though we set function in redux store , we can use that in dispatch function as an action because it returns a function which returns the action

  • In store
    This will be our action creators
export const sendCartData = (cart) => {
  return async (dispatch) => {
    dispatch(
      uiActions.showNotification({
        status: "pending",
        title: "Sending...",
        message: "Sending cart data",
      })
    );

    try {
      const response = await fetch(
        "https://react-http-975ab-default-rtdb.firebaseio.com/cart.json",
        {
          method: "PUT",
          body: JSON.stringify(cart),
        }
      );
      if (!response.ok) {
        throw new Error("Failed");
      }
      dispatch(
        uiActions.showNotification({
          status: "success",
          title: "Success!",
          message: "Sent cart data successfully",
        })
      );
    } catch (error) {
      dispatch(
        uiActions.showNotification({
          status: "error",
          title: "Error!",
          message: "Sending cart data failed",
        })
      );
    }
  };
};
  • In App.js
useEffect(() => {
    if (isInitial) {
      isInitial = false;
      return;
    }

    dispatch(sendCartData(cart));
  }, [cart, dispatch]);

Redux devTools

Find Chrome extension

profile
방황했습니다. 다시 웹 개발 하려고요!

0개의 댓글