I have a specific problem that is keeping me awake this whole week.
I have a parent component which has a pop-up children component. When I open the page the pop-up shows off and after 5 seconds it disappears with a setTimeout
.
This pop-up has an input element in it.
I want the pop-up to disappear after 5 seconds or if I click to digit something in the input. I tried to create a timerRef
to the setTimeout
and closes it in the children but it didn't work.
Can you help me, please? Thanks in advance.
ParentComponent.tsx
const ParentComponent = () => {
const [isVisible, setIsVisible] = useState(true)
timerRef = useRef<ReturnType<typeof setTimeout>>()
timerRef.current = setTimeout(() => {
setIsVisible(false)
}, 5000)
useEffect(() => {
return () => clearTimeout()
})
return (
<div>
<ChildrenComponent isVisible={isVisible} inputRef={timerRef} />
</div>
)
}
ChildrenComponent.tsx
const ChildrenComponent = ({ isVisible, inputRef}) => {
return (
<div className=`${isVisible ? 'display-block' : 'display-none'}`>
<form>
<input onClick={() => clearTimeout(inputRef.current as NodeJS.Timeout)} />
</form>
</div>
)
}
You're setting a new timer every time the the component re-renders, aka when the state changes which happens in the timeout itself.
timerRef.current = setTimeout(() => {
setIsVisible(false);
}, 5000);
Instead you can put the initialization in a useEffect
.
useEffect(() => {
if (timerRef.current) return;
timerRef.current = setTimeout(() => {
setIsVisible(false);
}, 5000);
return () => clearTimeout(timerRef.current);
}, []);
You should also remove the "loose" useEffect that runs on every render, this one
useEffect(() => {
return () => clearTimeout();
});