0

I seem to have an infinite loop in my code but I can't seem to see where, I usually see this if I am setting the state of something that is a dependency of useEffect but here the two variables (values / items) are completely seperate.

App.js

import React from 'react';
import './style.css';
import MyComponent from './MyComponent.js';

export default function App() {
  return (
    <div>
      <MyComponent />
    </div>
  );
}

MyComponent.js

import React, { useEffect, useState } from 'react';

const MyComponent = ({ values = [] }) => {

  console.log('MyComponent Reloaded');
  const [items, setItems] = useState();

  useEffect(() => {
    const loadItems = () => {
      //setItems([]);   //why does this cause infinite render loop?
    };

    loadItems();
  }, [values]);

  return <></>;
};

export default MyComponent;

Why does this cause a render loop?

I have an example build Here (Uncomment the commented line to begin render loop)

6
  • 1
    Your useEffect runs when you change values. You change values in that useEffect. Commented Aug 29, 2022 at 20:31
  • @KonradLinkowski Can you explain where I am changing values? The only place I set it is in the props Commented Aug 29, 2022 at 20:32
  • 2
    Oh sorry, I was wrong. You are creating new values in each render. Remember that [] !== [] so useEffect detect this a achange Commented Aug 29, 2022 at 20:33
  • So useState will cause a re-render, even if the state being changed isn't used in the output of the function? Commented Aug 29, 2022 at 20:40
  • 2
    Yes, change of state will always cause a re-render Commented Aug 29, 2022 at 20:41

2 Answers 2

1

You need to introduce the default values of the props the right way:

import React, { useEffect, useState } from 'react';

const MyComponent = ({ values }) => {
  console.log('MyComponent Reloaded');
  const [items, setItems] = useState();

  useEffect(() => {
    console.log(values)
    const loadItems = () => {
      setItems([]);
    };

    loadItems();
  }, [values]);

  return <></>;
};

MyComponent.defaultProps = {
  values: []
}

export default MyComponent;
Sign up to request clarification or add additional context in comments.

Comments

0

There are two possible bugs in the code:

  • According to your code, values variable is created every time, when checked with the previous values variable it is not same. So it causes infinite loop.

    • To fix this use default props.

      const MyComponent = ({ values }) => {
       ...
      
      MyComponent.defaultProps = {
        values: []
      }
      
  • As in your question,this line causes you the infinite loop

       //setItems([]);
    
    • To overcome this

      Add items dependency along with values, so that both values are watched before re-rendering.

      useEffect(() => {
      console.log(values)
      const loadItems = () => {
        setItems([]);
      };
      
      loadItems();
      }, [values,items]);
      

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.