vodanh
vodanh

Reputation: 79

useEffect goes in infinite loop when combined useDispatch, useSelector of Redux

I try to code with react-hook and redux for state management and axios for database requests with Thunk as middleware for handling asynchronicity.I'm having an issue in one component that does a get request to retrieve a list of customers on what used to be componentwillreceiveprop

# Action
export const actGetProductRequest = id => dispatch =>
  callApi(`products/${id}`, "GET").then(res =>
    dispatch({
      type: types.EDIT_PRODUCT,
      payload: { product: res.data }
    })
  );

------
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import useForm from "./useForm";
import { actGetProductRequest } from "../../actions";
...
const { history, match } = props;
  const getProduct = useSelector(state => state.itemEditing);
  const dispatch = useDispatch();
  const { values, setValues, handleChange, handleSubmit } = useForm(
    getProduct,
    history
  );  
  useEffect(() => {
    if (match) {
      let id = match.params.id;
      dispatch(actGetProductRequest(id));
    }
    setValues(()=>({...getProduct}));
  },[match,dispatch, setValues, getProduct]);

And I tried to call API and return the product, but the site always loop render infinite. Continuous rendering cannot be edited the form. like the

gif

Can anyone please help me out how to resolve this issue...

p.s: with code here, it run ok. But I want to use with redux, and I pass the code calling axios to the dispatch and redux to return the new changed state

 useEffect(() => {
    if (match) {
      let id = match.params.id;
      callApi(`products/${id}`, "GET", null).then(res => {
        const data = res.data;
        setValues(()=>({...data}));
      });      
    }
    const clearnUp = () => setValues(false);
    return clearnUp;
  },[match, setValues]);

p.s: full code code

Upvotes: 6

Views: 6259

Answers (1)

Praneeth Paruchuri
Praneeth Paruchuri

Reputation: 1032

Just get the id from the history > match

  const { history, match } = props;  
  const id = match ? match.params.id : null;

You don't need to add dispatch to the dependencies. Instead of match, use id. And you can skip the method references. Since setValues is basically a setState call, it can be skipped too (Read React docs). But if you do want to use any function references in dependecies, make sure you wrap them with useCallback.

  useEffect(() => {
    if (id) {
      dispatch(actGetProductRequest(id));
    }
    setValues(()=>({...getProduct}));
  },[id, getProduct]); 

Your main issue might be with the match object. Since, history keeps changing, even if the id is the same.

Upvotes: 2

Related Questions