Should I run asynchronous code in an useEffect hook or in an action-creator-thunk

Viewed 350

I am going through the tutorial of react and Max discusses about action creator thunk in the Redux section . However the async code can be written in both useEffect hook and also using action-creator-thunk . Which approach will be better ? Will writing a separate action-creator-thunk instead of useffects give any extra benefit or performance gain .

code for action-creator-thunk cart-actions.js

export const fetchCartData = () => {
  return async (dispatch) => {
    const fetchData = async () => {
      const response = await fetch(
        'https://react-http-6b4a6.firebaseio.com/cart.json'
      );

      if (!response.ok) {
        throw new Error('Could not fetch cart data!');
      }

      const data = await response.json();

      return data;
    };

    try {
      const cartData = await fetchData();
      dispatch(
        cartActions.replaceCart({
          items: cartData.items || [],
          totalQuantity: cartData.totalQuantity,
        })
      );
    } catch (error) {
      dispatch(
        uiActions.showNotification({
          status: 'error',
          title: 'Error!',
          message: 'Fetching cart data failed!',
        })
      );
    }
  };
};

code for useEffect

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

  useEffect(() => {
    const sendCartData = async () => {
      dispatch(
        uiActions.showNotification({
          status: 'pending',
          title: 'Sending...',
          message: 'Sending cart data!',
        })
      );
      const response = await fetch(
        'https://react-http-6b4a6.firebaseio.com/cart.json',
        {
          method: 'PUT',
          body: JSON.stringify(cart),
        }
      );

      if (!response.ok) {
        throw new Error('Sending cart data failed.');
      }

      dispatch(
        uiActions.showNotification({
          status: 'success',
          title: 'Success!',
          message: 'Sent cart data successfully!',
        })
      );
    };

    if (isInitial) {
      isInitial = false;
      return;
    }

    sendCartData().catch((error) => {
      dispatch(
        uiActions.showNotification({
          status: 'error',
          title: 'Error!',
          message: 'Sending cart data failed!',
        })
      );
    });
  }, [cart, dispatch]);

  return (
    <Fragment>
      {notification && (
        <Notification
          status={notification.status}
          title={notification.title}
          message={notification.message}
        />
      )}
      <Layout>
        {showCart && <Cart />}
        <Products />
      </Layout>
    </Fragment>
  );
}
1 Answers

However the async code can be written in both useEffect hook and also using action-creator-thunk . Which approach will be better ?

It depends on your requirements and architecture. Redux implements the flux architecture.

The main difference between redux thunk and the useEffect approach is that a redux thunk can be dispatched from anywhere (not even a component) while the useEffect is bound to a component.

The redux thunk is easier to test, because it is isolated from the component. Of course you can also achieve better testing with the useEffect approach by extracting the logic into a separate function, but then your extracted function will become a "thunk-like" function.

Related