useState() - doesn't seem to work as expected

Ethan

I am writing a modal component in React. The logic is simple, first pass the variable visible as props to the component modal. Then the external component updates the state of the modal by controlling visible. But I got an issue where modal didn't turn off after the external component set visible to false, and it didn't seem like setState was in effect.

I have provided the complete demo code, you can see the log that the visible object is not change as I set a new Object to it.

Code sandbox click to see demo

I hope you can help me look at this problem, thank you very much!

export default function () {
  const [visible, setVisible] = useState(() => ({
    m1: false,
    m2: false,
    m3: false
  }));

  const close = useCallback(() => {
    const s = { ...visible, m1: false };
    console.log("should be: ", s);
    setVisible(s);
  }, []);

  useEffect(() => {
    console.log("newVal: ", visible);
  }, [visible]);

  const props = {
    components: [
      {
        component: (
          <button
            onClick={() => {
              setVisible({ ...visible, m1: true });
            }}
          >
            open Modal1
            <Modal visible={visible.m1} close={close}>
              this is a modal
            </Modal>
          </button>
        )
      }
    ]
  };

  return <IntroComponent {...props} />;
}

enter image description here

Cody Duong

This is because your Modal is not actually a Modal. It is a child of <button {...}/>, likewise when button is clicked, it will make m1: false, but the event bubbles up to the Modal onClick handler making m1: true again.

          <button
            onClick={() => {
              console.log("Activated!");
              // When you click on the Modal component, this will also trigger.
              setVisible({ ...visible, m1: true });
            }}
          >
            open Modal1
            <Modal visible={visible.m1} close={close}>
              this is a modal
            </Modal>
          </button>

When you change the DOM structure you can see it works just fine. (side note: <> is syntactic sugar for fragments). So this will work:

component: (
          <>
            <button
            onClick={() => {
              setVisible({ ...visible, m1: true });
            }}
            >
              open Modal1
              
            </button>
            <Modal visible={visible.m1} close={close}>
              this is a modal
            </Modal>
          </>
        )

@John has the right idea, and while it technically solves the issue, it is more a workaround than an actual desirable outcome. See Q: When is good practice to use stopPropagation()?

Also when I see language like Modal, for your consideration is the ReactPortal. However, it is a complex topic that requires some understanding about how the DOM and VDOM interact, and beyond the scope of this Q/A.

View CodeSandbox

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Strcmp doesn't work and I don't seem to understand why - transformation to ASCII code makes the program work as expected though

java.util.Date equals() doesn't seem to work as expected

golang TCPConn.SetWriteDeadline doesn't seem to work as expected

LIKE doesn't seem to work

DispatchGroup doesn't work as expected

Completed property in Angular Material Stepper doesn't seem to work as expected

Volatile doesn't work as expected

Script defer doesn't seem to work as expected

Jekyll "where" filter with site.data doesn't seem to work as expected

React useState method in function doesn't work as expected

Angular 8 .next doesn't seem to work as expected

didChangeAppLifecycleState doesn't work as expected

Rails SQL select, doesn't seem to work as expected with the CASE statement

pysftp.connection.cd() doesn't seem to work as expected - any ideas why

Object_hook in json module doesn't seem to work as expected

.gitignore Doesn't Seem To Work

SharedPreferences doesn't seem to work

memcache doesn't work as expected

Sorting doesn't seem to work

setLocation on a JButton doesn't seem to work as expected

grep doesn't work as expected

:not() doesn't work as expected

subquery doesn't seem to work

Mockito thenAnswer doesn't seem to work as expected

totalSizeCap in logback doesn't seem to be working as expected

AMQP.Net Credit doesn't seem to work as expected

The date functions in snowflake doesn't seem to work as expected

React useState hook doesn't work as expected

React TS universal hack for inputs with useState doesn't work as expected