skip to Main Content

I am fetching a list of series from the MySQL db using Express API. I checked on Express logs and see the request is made 2 times. I console logged the react component and the useEffect hook and see the component itself is rendered 5-6 times and the useEffect his rendered 2 times (based on the console log outputs in the chrome browser). What am i doing wrong? Here is my code:

import React, { useState, useEffect } from 'react';
import { useDispatch, useSelector } from "react-redux";
import { fetchSeries } from '../../Redux/Actions/SeriesActions';

const MyList = () => {
  const [isSeriesOpen, setIsSeriesOpen] = useState(false);
  const dispatch = useDispatch();
  const series = useSelector((state) => state.seriesList.series);
  const userId = useSelector((state) => state.auth.user_id);
  const companyId = 3;

  console.log("Log from the component");

  useEffect(() => {
    dispatch(fetchSeries(userId, companyId));
    console.log("Log for Effect called");
  }, [dispatch]);


  return (
    <div>
      <p> Test Content</p>
    </div>
  );
};

export default MyList;

I tried checking if there is anything making the component re-render. The component is imported in the Routes which is imported in the App.js which is imported in index.js. But this is a normal structure for React, isnt it? I dont undertsnad why useEffect is called 2 times and hence 2 requests are made to the api causeing it to run query on the db 2 times.

4

Answers


  1. React renders twice while in development.

    See:

    " Strict mode can’t automatically detect side effects for you, but
    it can help you spot them by making them a little more deterministic.
    This is done by intentionally double-invoking the following functions:
    Class component constructor , render , and shouldComponentUpdate
    methods."

    Source: React Docs: Strict Mode

    Also, you should add all the variables that are used inside the useEffect, into the dependency array at the end

      useEffect(() => {
        dispatch(fetchSeries(userId, companyId));
        console.log("Log for Effect called");
      }, [dispatch, userId, companyId]);
    
    Login or Signup to reply.
  2. Currently, you have [dispatch] as the dependency array, which means the effect will be re-executed whenever dispatch changes. Since dispatch is a function provided by Redux, it will change on every render, leading to the effect being executed multiple times.

    To fix this issue, you should include all dependencies that affect the effect inside the dependency array. In your case, userId and companyId are likely the dependencies that should trigger the effect to re-run when they change. Here’s how you can modify your useEffect hook:

    useEffect(() => {
      dispatch(fetchSeries(userId, companyId));
      console.log("Log for Effect called");
    }, [dispatch, userId, companyId]);
    
    Login or Signup to reply.
  3. In your code, the useEffect is set up to run whenever the dispatch function changes. Since dispatch is a function created by useDispatch, it will always change between renders. This is a common pitfall with Redux when used with React hooks.

    Here’s a modified version of your code that should resolve the issue:

    import React, { useState, useEffect } from 'react';
    import { useDispatch, useSelector } from "react-redux";
    import { fetchSeries } from '../../Redux/Actions/SeriesActions';
    
    const MyList = () => {
      const [isSeriesOpen, setIsSeriesOpen] = useState(false);
      const dispatch = useDispatch();
      const series = useSelector((state) => state.seriesList.series);
      const userId = useSelector((state) => state.auth.user_id);
      const companyId = 3;
    
    console.log("Log from the component");
    
      useEffect(() => {
       // Move dispatch outside the useEffect dependencies
        dispatch(fetchSeries(userId, companyId));
       console.log("Log for Effect called");
     }, [dispatch, userId, companyId]);  // Now include userId and companyId in the 
     dependencies array
    
     return (
       <div>
         <p> Test Content</p>
       </div>
      );
    };
    

    export default MyList;

    By adding userId and companyId to the dependency array, you’re ensuring that the effect will only run when these values change. This should help prevent unnecessary API calls and resolve the issue of useEffect being called multiple times.

    Login or Signup to reply.
  4. 1.Without Dependencies:

    If you pass an empty dependency array ([]) to useEffect, it runs once after the initial render.
    If you omit the dependency array entirely, it runs after every render.

        useEffect(() => {
      // This code runs after the initial render or after every render.
      // It is equivalent to componentDidMount and componentDidUpdate.
        }, []);
    

    2.With Dependencies:

    If you provide dependencies in the dependency array, useEffect will run after the initial render and whenever any of the specified dependencies change.
    This helps in controlling when the effect should run based on the changes in specific variables.

    useEffect(() => {
        // This code runs after the initial render and whenever 'variable' 
        changes.
        // It is equivalent to componentDidMount and componentDidUpdate based 
        on 'variable'.
        console.log('Effect ran!');
      }, [variable]);
    

    3.Without Dependencies Array:

    If you don’t pass any dependencies array to the useEffect, it means the effect will run after every render of the component it means infinity times. This is similar to having a dependency array with no dependencies.

    useEffect(() => {
      // This code runs after every render.
      // It is equivalent to componentDidUpdate.
    });
    

    The effect will run after the initial render.It will run again whenever the component re-renders, regardless of the reason for the re-render.It’s useful for situations where you want the effect to run after every update or if the effect doesn’t depend on any specific values.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search