Home > Software engineering >  useEffect infinite loop issue with default prop value
useEffect infinite loop issue with default prop value

Time:10-18

I have a dropdown component; important part of it here:

import { useEffect, useState } from "react"

type PropsType = {
    options?: any[]
}

export const DropDown = (props: PropsType) => {

    const { options = [] } = props;

    const [query, setQuery] = useState('');

    const [filteredOptions, setFilteredOptions] = useState([]);

    useEffect(() => {
        setFilteredOptions(()=>[]); // calculate the filtered options according to the options and query cahnges
    }, [query, options])

    return (
        <div>
            DropDown
        </div>
    )
}

As you see, I have an options property, that if you do not specify it, it would be an empty array.

This is the simple use case of this component:

<DropDown options={[]} />

But if you set options property to undefined:

<DropDown options={undefined} />

...you will get an infinite loop.

It is important that I know how to solve the infinite loop by using useRef

But there will be another problem after using useRef:

If you use useRef to solve the problem, if you change options value during the runtime, for example after calling an API and change the options state, in the dropdown component, the useEffect will not trigger.

What should I do to have a dynamic options without getting infinite loop when someone sets it to undefined?

What is going on under the hood?

import { useEffect, useState } from "react";
import { DropDown } from "./dropdown";
function App() {
  const [options,setOptions] = useState<string[]>([]);
  useEffect(()=>{
    setOptions(()=>['a','b'])
  },[])
  return (
    <div>
      <DropDown options={options}/>
    </div>
  );
}

CodePudding user response:

I believe that the problem here is that you have default value for options. UseEffect triggers new render, on that render you get a new options (because empty array will have new link to memory each time its created, and its created on each render), that new options array trigger useEffect that cause a new render and it goes to infinite loop.

I think after understanding this, it would be easy for you to fix this. The easiest fix that should work (but I'm not sure) is to set Dropdown.defaultProps, so you would set options there instead of component itself.

Good luck!

CodePudding user response:

  1. You can try the solution i tested in the sandbox which uses the logical && operator

Kindle Check the Sand Box : DEBUG USING && Operator when options = undefined

Tip 4: Destructuring to access object properties- By Dmitri Pavlutin Logical AND (&&)

useEffect(()=>{
   setFilteredOptions(()=>[])
  },[])

To Answer the first part of your question This error can be solved by mentioning in an Empty Dependency Array as a possible fix however not in your case since your passing dependencies .

According to blog.logrocket.com How to solve the React useEffect Hook’s infinite loop patterns

Which states examples for the patterns that make an infinite loop in React useEffect Hook

  1. .No dependency Array

  2. Revoking and repeating the function in useEffect

  3. Mentioning a function as a dependency

Fixes for Each Pattern

1.Mention the Empty Dependency Array ,[] before the end of the useEffectHook

2.Remove any Repeated function declaration in useEffect

3.Mention function as a function not as a property and add in the dependencies to the dependency array ,[dependency] for example

  • Related