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:
- You can try the solution i tested in the sandbox which uses the logical
&&
operator
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
.No dependency Array
Revoking and repeating the function in useEffect
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