2

I'm trying to implement the following yes/no buttons:

import React, { useState } from "react";

const YesNoComponentFunctional = () => {
  const [button, setButton] = useState("");

  const onYesPress = () => {
    setButton("Yes");
    console.log({ button });
  };

  const onNoPress = () => {
    setButton("No");
    console.log({ button });
  };

  return (
    <div>
      <button onClick={() => onYesPress()}>Yes</button>
      <button onClick={() => onNoPress()}>No</button>
     </div>
  );
};
export default YesNoComponentFunctional; 

Wich I got from this article here.

And I can't understand why I have to click the buttons twice to properly display the message to console. Why is that happening?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Rogerio Schmitt
  • 1,055
  • 1
  • 15
  • 35
  • 4
    Setting state in react isn't a synchronous task, your `console.log` is probably being called before the state has actually changed. – DBS Jan 14 '20 at 11:59
  • Because `setButton` runs asynchronously. The value of `button` is actually updated after the the line `console.log` – Loi Nguyen Huynh Jan 14 '20 at 12:01
  • https://github.com/bilalsha/react-guide Take a look at it it is also using hooks – Bilal Shah Jan 14 '20 at 12:05

2 Answers2

3

setButton is async method, your button state won't update immediately. you can use useEffect hook to check if button's values is updated or not.

useEffect(() => {
  console.log({button});
}, [button]);
Amit Chauhan
  • 6,151
  • 2
  • 24
  • 37
1

The set function(setButton for this example) is asynchronous. In order to get the exact result, you need to use useEffect.

import React, { useState, useEffect } from "react";

const YesNoComponentFunctional = () => {
  const [button, setButton] = useState("");

  const onYesPress = () => {
    setButton("Yes");
  };

  const onNoPress = () => {
    setButton("No");
  };
  
  useEffect(() => {
    console.log({button})
  }, [button])

  return (
    <div>
      <button onClick={() => onYesPress()}>Yes</button>
      <button onClick={() => onNoPress()}>No</button>
     </div>
  );
};
export default YesNoComponentFunctional;
TopW3
  • 1,477
  • 1
  • 8
  • 14
  • If it's async, shouldn't I be able to solve that by awaiting it? – Rogerio Schmitt Jan 14 '20 at 12:04
  • 'asynchronous' doesn't mean awaitable. For example, 'asynchronous' means that the function isn't blocked until the function is completed. We can take fs.readFile function as an asynchronous function example. – TopW3 Jan 14 '20 at 12:08