0

I was using useState hook and it seems that the hook is not working properly. When I click on one of my radio buttons initially it logs nothing, but after my second click it logs the previous one that I clicked. Every time I click on any button It logs the button that I previously clicked. #sidenote: (The 'info' that I've imported is an array of objects and each 'incorrect_answers' property has an array as value) . Here is my code:

import React, {useState} from 'react'
import { info } from "./data";

const Quiz = () => {

const [i, setI] = useState(0);
const [value, setValue] = useState('');

const {correct_answer, incorrect_answers} = info[i]
const arr = [correct_answer, ...incorrect_answers].sort((a, b) => a.length - b.length);
console.log(arr)

const handleSubmit = (e) => {
    e.preventDefault();
    setI(i + 1);
}

const handleChange = (e) => {
    setValue(e.target.value);
    console.log(value);
}

return (
    <div className="quiz">
        <form className='quiz__form' onSubmit={(e) => handleSubmit(e)}>
            <div className="form__body" >
                {arr.map((item, index) => {
                    return (
                        <div className="form__item" key={index}>
                            <label htmlFor={`option-${index}`}>
                                <input 
                                    type="radio" 
                                    name="options" 
                                    id={`option-${index}`}
                                    value={item}
                                    onClick={(e) =>  handleChange(e)}
                                /> {item}
                            </label>
                        </div>
                    )
                })}
            </div>  
        </form>
    </div>
)
}

Can anyone tell me where I am wrong?

danhuong
  • 202
  • 1
  • 8
Saimur Rahman
  • 31
  • 1
  • 6
  • your question is similar to https://stackoverflow.com/questions/66350320/react-usestate-is-always-behind-1-step/66351824#66351824 – danhuong Feb 25 '21 at 17:54
  • You are logging the old value with `console.log(value)` because `setValue(e.target.value)` updates the contents of `value` on the next render, not on the current one. If you want to use the "new" contents of `value`, just use the same source. eg. `const value = e.target.value` (create a shadow variable) then `setValue(value)` (update the render variable (on the next render)) and `console.log(value)` (log the new value). – 3limin4t0r Feb 25 '21 at 18:10
  • See also: [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – 3limin4t0r Feb 25 '21 at 18:12

2 Answers2

2

setValue is asynchronus. So you will have to wait to see the change. One thing you can do to see the change is add this following code

useEffect(() => {
    console.log(value)
}, [value])

This way you can see when the value of the value changes

Mohammad Faisal
  • 2,265
  • 1
  • 10
  • 16
1

The setState function in reactjs (setValue in your case) is an asynchronous function, it update the state at the end of the event handler (handleChange), so the value variable wil still refer the previous state inside the event handler (handleChange).

Try to add console.log before the returned JSX, then click on input radio you see log after the event handler was executed

const handleChange = (e) => {
    setValue(e.target.value);
    console.log(value);
}
console.log("value after handle event",value);
return (

For more information about hou reactjs update state please check here

ARZMI Imad
  • 950
  • 5
  • 8