Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React hooks toggle setState

so far I saw two ways to handle toggle

first, set state based on previous state

export default function App() {
  const [show, setShow] = useState(false);
  const handleClick = () => {
    setShow(s => !s);
  };
  return (
    <div>
      <div>show: {String(show)}</div>
      <button onClick={handleClick}>BTN</button>
    </div>
  );
}

second, pass the state directly as the argument

export default function App() {
  const [show, setShow] = useState(false);
  const handleClick = () => {
    setShow(!show);
  };
  return (
    <div>
      <div>show: {String(show)}</div>
      <button onClick={handleClick}>BTN</button>
    </div>
  );
}

which one is correct? In my understanding the second may not work as set state is async, it may not be able to get the correct state if I click the button several times

like image 592
peace and love Avatar asked Apr 20 '20 00:04

peace and love


People also ask

How do you toggle a button in useState react?

js import React, { useState } from "react"; import styled from "styled-components"; import { menuData } from "./menuData"; import NavigationButton from "./NavigationButton"; const Menu = () => { const [isOpen, setIsOpen] = useState(false); return ( <Wrapper> <NavigationButton onClick={() => setIsOpen(!

How do you toggle in a functional component react?

The sample React button component that toggles between on and off is provided below. import React, { useState } from 'react'; import ReactDOM from 'react-dom'; const buttonToggle = () => { const [isOff, setIsOff] = useState(true); return ( <button onClick={() => setIsOff(! isOff)}>{ isOff ?

Do react hooks replace state?

Hooks are a more direct way to use the React features you already know — such as state, lifecycle, context, and refs. They don't fundamentally change how React works, and your knowledge of components, props, and top-down data flow is just as relevant.


1 Answers

The first one is correct:

setShow(s => !s);

Although the second one works in this case it is not correct:

// bad code
setShow(!show);

Why?

Setting state is asynchronous - but what that really means is that setting state is deferred until re-render.

An example:

const [myNum, setMyNum] = useState(0)

const handleUpdate = () => {
  setMyNum(myNum + 1)
}

If we call the handleUpdate function, the new value of myNum is incremented by 1. That works correctly, but what about this:

const [myNum, setMyNum] = useState(0)

const handleUpdate = () => {
  setMyNum(myNum + 1)
  setMyNum(myNum + 1)
}

You may think that myNum is now 2, but it's not, it's still 1.

This happens because the value of myNum does not change until re-render, so you're essentially writing this:

const handleUpdate = () => {
  setMyNum(0 + 1)
  setMyNum(0 + 1)
}

That is why you should always provide a function to set state if you depend on the previous value.

This works correctly:

const handleUpdate = () => {
  setMyNum(p => p + 1)
  setMyNum(p => p + 1)
}

myNum is now 2.

Even if you're only setting the value once, you should maintain good practice. When your app gets complex and several different actions may set the state at any time, you don't want to be caught out by something you wrote months ago that you never thought was going to matter.

like image 121
JMadelaine Avatar answered Sep 30 '22 03:09

JMadelaine