Search code examples
reactjsreduxrouteruse-effectuse-state

react redux dispatches for infinite time with useEffect


I am really having a hard time with this, if anyone could help, i would really appreciate. So, what I am trying to do is, after the listFeatured() is fetched, set the home(setHome) its one of the value. But instead it dispatches for unlimited time. I removed rest of the code similar to below, but still doesn't work.

import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { WEIGHTS } from '../constants';
import { 
    listFeatured, 

} from '../actions/featuredActions';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';


const Featured = () => {
    const navigate = useNavigate();
    const dispatch = useDispatch();

    const [home, setHome] = useState();


    const userLogin = useSelector((state) => state.userLogin);
    const { userInfo } = userLogin;

    const featuredList = useSelector((state) => state.featuredList);
    const { featured } = featuredList;

    useEffect(() => {
        if(userInfo) {
            dispatch(listFeatured())
        }else if (featured) { 
            setHome(featured.featured_home)
        } else {
             navigate('/')
        }
          
  }, [dispatch, navigate, userInfo, featured])


    return(
        <Wrapper>
            <h1></h1>
        </Wrapper>
        
    )
}

const Wrapper = styled.div`
    display: flex;
    padding: 20px 20px;
    flex-direction: column;
    margin-top: 100px;
    justify-content: center;
    align-items: center;
`;

export default Featured;


Solution

  • You probably have an infinite dispatch because everything is done in the same useEffect, here is the flow:

    • it goes inside the useEffect
    • you have userInfo
    • you dispatch listFeatured
    • it update featuredList
    • then it re-run your useEffect because featuredList changed
    • you have userInfo
    • you dispatch listFeatured
    • it update featuredList
    • etc...

    Use a selector when you derivate state

    featuredList comes from the state and it's use to create home. Then home variable can be derivated from the state and just be a selector, it will avoid re-rendering for nothing.

    Here is an example:

    const userInfo = useSelector((state) => state.userLogin.userInfo);
    const featuredList = useSelector((state) => state.featuredList);
    const home = useSelector((state) => state.featuredList.featured.featured_home);
    
    useEffect(() => {
      if(userInfo) {
        dispatch(listFeatured())
      } else {
        navigate('/')
      }          
    }, [navigate, userInfo])