const Navbar = () => {
const [isModalOpen, setisModalOpen] = useState(true)
const [isLogin, setisLogin] = useState(true)
const onClose = () =>{
setisModalOpen(false)
if(!isLogin){
setisLogin(true)
}
}
return (<Modal isOpen={isModalOpen} onClose={() => onClose()} >
{!isLogin ?
<Register />
:
<Login setisLogin={() => setisLogin(false)} />
}
</Modal>)
}
when I call onclose Function component gets re-renders once with the value of login then the modal is closing
Using setTimeout is solving my problem but I think using setTimeout is not a good practice.
const Navbar = () => {
const [isModalOpen, setisModalOpen] = useState(true)
const [isLogin, setisLogin] = useState(true)
const onClose = () =>{
setisModalOpen(false)
setTimeout(() => {
if(!isLogin){
setisLogin(true)
}
}, 300);
}
return (<Modal isOpen={isModalOpen} onClose={() => onClose()} >
{!isLogin ?
<Register />
:
<Login setisLogin={() => setisLogin(false)} />
}
</Modal>)
}
There are couple of ways you can achieve this. i am posting the useEffect way.
you can use useEffect and listen on the isLogin if it changes trigger the setisLogin() function.
code
const Navbar = () => {
const [isModalOpen, setisModalOpen] = useState(true)
const [isLogin, setisLogin] = useState(true)
React.useEffect(() => {
if(!isLogin){
setisLogin(true);
}
},[isModalOpen])
const onClose = () =>{
setisModalOpen(false)
}
return (<Modal isOpen={isModalOpen} onClose={() => onClose()} >
{!isLogin ?
<Register />
:
<Login setisLogin={() => setisLogin(false)} />
}
</Modal>)
}
useState and setState both are asynchronous in nature already.
Like Shoyeb Memon mentioned, you can use React's useEffect hook to "listen" to changes with isModalOpen and act upon those changes.
The implementation should look like this:
const onClose = () =>{
setisModalOpen(false)
}
useEffect(() => {
if(!isLogin){
setisLogin(true)
}
}, [isModalOpen]);
This is the way we usually handle this types of situation in React,
where we need to act upon a change in state or in values that we receive asynchronously.