Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 809
vodanh Avatar asked Sep 13 '19 13:09

vodanh


People also ask

How do you stop an infinite loop in useEffect?

To get rid of your infinite loop, simply use an empty dependency array like so: const [count, setCount] = useState(0); //only update the value of 'count' when component is first mounted useEffect(() => { setCount((count) => count + 1); }, []); This will tell React to run useEffect on the first render.

Should you combine hooks with Redux?

We recommend using the React-Redux hooks API as the default approach in your React components. The existing connect API still works and will continue to be supported, but the hooks API is simpler and works better with TypeScript. These hooks were first added in v7.1.0.

Can we use useEffect in Redux?

We import the needed from react, react-native and react-redux. Also import your fetch funtcion from the action file. We'll be using the useEffect function for making sure our function is called the right way.


1 Answers

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.

like image 57
Praneeth Paruchuri Avatar answered Nov 15 '22 05:11

Praneeth Paruchuri