skip to Main Content

I have a form on my website with a default value of ethExperienceLevel set to "BEGINNER". I have a function to change the selected state when I switch between options in a select element dropdown list with an onChange handler. However, e.target.value of the selected element is always the currently selected option’s value, but when I am setting that to ethExperienceLevel on the form the value gets set to one option that was previously selected before the onChange. I do not understand why.

const [form, setForm] = useState<IHackerInput>({
    email: '',
    firstName: '',
    lastName: '',
    website: '',
    github: '',
    linkedIn: '',
    yearsOfSoftwareExperience: 0,
    ethExperienceLevel: 'BEGINNER',
    motivation: 'ATTENDWORKSHOPS',
    priorBuilds: '',
    lookingToBuild: '',
    rulesAccepted: false,
  })

  const handleETHExperienceSelect = (
    e: ChangeEvent<HTMLSelectElement>,
  ): void => {
    if (
      e.target.value === 'BEGINNER' ||
      e.target.value === 'INTERMEDIATE' ||
      e.target.value === 'EXPERT'
    ) {
      console.log(e.target.value) // correctly selected option value
      setForm({ ...form, ethExperienceLevel: e.target.value })
      console.log(form.ethExperienceLevel) // option before selected change 
    }
  }
                <label
                  htmlFor="ethExperienceLevel"
                >
                  What's your experience level with Ethereum?
                </label>
                <select
                  id="ethExperienceLevel"
                  onChange={(e) => handleETHExperienceSelect(e)}
                >
                  <option value="BEGINNER">beginner</option>
                  <option value="INTERMEDIATE">intermediate</option>
                  <option value="EXPERT">expert</option>
                </select>

2

Answers


  1. I think that is related to how setState works in react.js.setState is an async operation but it does not return a Promise, so you cannot use await or then

    setState will cause your component rerendering and when your component rerenders, you will have the updated state value. However, for the performance reason, react decides when to rerender the component.

    when you called console.log(form.ethExperienceLevel) your component has not been rerendered. if you run console.log("chekcing the update",form.ethExperienceLevel) outside the function, last console will be the updated the value.

    Login or Signup to reply.
  2. What happens is that setForm is executed asynchronously by React, so it is not guaranteed to be executed immediately after you call it, to be notified the exact moment when React execute setForm (and therefore the value of form changes) you will have to watch for the changes in form, so we need to use useEffect:

    useEffect(() => {
      // actions to perform when the form value changes
    }, [ form ]) // here we are watching for changes in form
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search