Here is my component code:
import React from "react";
import { useState } from "react";
import { Text, SvgContainer, Svg, Flex } from "../lib/styles";
import Modal from "./Modal";
const Credits = () => {
const [modal, setModal] = useState(false);
const openModal = () => {
alert("state should change")
setModal(true);
alert("after");
};
const closeModal = () => {
setModal(false);
};
return (
<Flex>
<Text $SubHeader>Crafted By Michele Staffiere 2023</Text>
<SvgContainer onClick={()=>{openModal()}}>
<Svg src="/assets/question-mark.svg" />
</SvgContainer>
<Modal isOpen={modal} Close={closeModal} Open={openModal} />
</Flex>
);
};
export default Credits;
I’m trying to toggle the state of my modal with this element:
<SvgContainer onClick={()=>{openModal()}}>
<Svg src="/assets/question-mark.svg" />
</SvgContainer>
The issue is that the openModal()
function isn’t updating my state at all – it remains false. My alerts trigger both before and after the setModal(true)
so why is my state remaining as false
in my dev tools? This is resulting in my modal never actually popping up on page.
When I go into my dev tools and manually set the state to true
, my modal opens fine and the close modal function works fine as well when I click outside the modal area.
Why is my:
const openModal = () => {
alert("state should change")
setModal(true);
alert("after");
};
not updating the state at all?
2
Answers
The problem is how you pass your callback function. One of the correct variants would be:
or
Check out more in react documentation (Pitfall chapter): https://react.dev/learn/responding-to-events
Be aware that the "set state function" is an asynchronous function. When your code first hits the call, it puts the call onto JavaScript’s "asynch queue" to be executed later, then JS continues running….executing your second
alert()
before the asynchronous code gets executed.This is the way that JavaScript works.
I strongly encourage all of my friends (and make it a requirement of all of my coworkers) to watch the video JavaScript: Understanding the Weird Parts multiple times. Especially the parts about Synchronous and Asynchronous code execution (time links are in the video description).
If this were me, I would add
console.log("modal is:", modal);
immediately before thereturn()
that returns the JSX for your component. That will let you see the value every single time the component renders.