skip to Main Content

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


  1. The problem is how you pass your callback function. One of the correct variants would be:

    <SvgContainer onClick={openModal}>
    

    or

    <SvgContainer onClick={() => openModal()}>
    

    Check out more in react documentation (Pitfall chapter): https://react.dev/learn/responding-to-events

    Login or Signup to reply.
  2. 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 the return() that returns the JSX for your component. That will let you see the value every single time the component renders.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search