Monty Tomar
Monty Tomar

Reputation: 65

dispatching actions on every render

I am dispatching action addProducts on every mount of the ProductList component whereas i want to dispatch the action one timeusing useEffect hook and store the data in the redux and then use it.

Below are my actions file and ProductList component file.

actions.js file

export const addProducts = () => async (dispatch) => {
  let Products = await axios.get("https://api.npoint.io/2a4561b816e5b6d00894");
  return dispatch({
    type: ADD_PRODUCTS,
    payload: Products.data,
  });
};

ProductList.js component file

import { addProducts } from "../actions/Index";
const ProductList = () => {
  const dispatch = useDispatch();
  useEffect(() => {
   dispatch(addProducts()); 
  },[]);
  const Products = useSelector((state) => state.products);
  console.log(Products)

Upvotes: 2

Views: 85

Answers (3)

peter554
peter554

Reputation: 1378

You want to check if products are already in redux with an if(!products){...} e.g.

const addProducts = () => async (dispatch) => {
  let Products = await axios.get("https://api.npoint.io/2a4561b816e5b6d00894");
  return dispatch({
    type: ADD_PRODUCTS,
    payload: Products.data,
  });
};

const ProductList = () => {
  const dispatch = useDispatch();
  const products = useSelector((state) => state.products);
  useEffect(() => {
   if (!products) {
     dispatch(addProducts()); 
   }
  },[dispatch]);
  return <p>foo</p>
}

Upvotes: 2

HMR
HMR

Reputation: 39340

You could just dispatch the action in the component but in the thunk action do nothing if products are available:

export const addProducts = () => async (
  dispatch,
  getState,//thunk also get a getState function
) => {
  //you should write a dedicated selector function so you could do:
  //  const productsInState = selectProducts(getState())
  const productsInState = getState().products
  //whatever would make state.products available
  //  reducers are missing in your question
  if(productsInState){
    //do nothing if products are already in state
    return;
  }
  let Products = await axios.get(
    'https://api.npoint.io/2a4561b816e5b6d00894',
  );
  return dispatch({
    type: ADD_PRODUCTS,
    payload: Products.data,
  });
};

In your component you can just dispatch on each render, if your page has multiple components dispatching this action then you could make a grouped action.

Upvotes: 2

Hend El-Sahli
Hend El-Sahli

Reputation: 6752

export const addProducts = () => async dispatch => {
  dispatch({
    type: ADD_PRODUCTS_START,
    payload: { loading: true },
  });

  const Products = await axios.get(
    'https://api.npoint.io/2a4561b816e5b6d00894'
  );

  dispatch({
    type: ADD_PRODUCTS_SUCCESS,
    payload: { products: Products.data, loading: false },
  });
};

const ProductList = ({ products, loading }) => {
  useEffect(() => {
    if (!products && !loading) {
      dispatch(addProducts());
    }
  }, []);
};


const mapStateToProps = ({ products: { data, loading } }) => ({ products: data, loading });

Upvotes: 1

Related Questions