title: React TypeScript: Multiple State updates but only first one gets applied
body: <p>I made a sandBox here <a href="https://codesandbox.io/s/old-mountain-xl7nz" rel="nofollow noreferrer">https://codesandbox.io/s/old-mountain-xl7nz</a> when you don't full in any of the form inputs I expect to see 3 errors but I only get one. I don't understand why</p>
  
  <pre><code>import React, { ChangeEvent, useState } from 'react';
  import { Link } from 'react-router-dom';
  import loadingImg from '../images/loading.svg';
  
  const Join: React.FC = () =&gt; {
    const [state, setState] = useState({
      email: '',
      emailError: '',
      fullName: '',
      fullNameError: '',
      loading: false,
      password: '',
      passwordError: '',
    });
    const {
      email,
      emailError,
      fullName,
      fullNameError,
      password,
      passwordError,
    } = state;
  
    const onChange = (event: ChangeEvent&lt;HTMLInputElement&gt;) =&gt; {
      event.persist();
      setState((prev) =&gt; ({
        ...prev,
        [event.target.id]: event.target.value,
      }));
    };
    const onSubmit = (event: React.FormEvent) =&gt; {
      event.preventDefault();
      if (validate('fullName') &amp;&amp; validate('email') &amp;&amp; validate('password')) {
        console.log('FIRE FORM');
      }
    };
    const onBlur = (event: ChangeEvent&lt;HTMLInputElement&gt;) =&gt; {
      validate(event.target.id);
    };
    const validate = (id: string) =&gt; {
      switch (id) {
        case 'fullName':
          if (!/^.{6,7}$/.test(fullName)) {
            setState((prev) =&gt; ({ ...prev, fullNameError: 'err' }));
            return false;
          } else {
            setState((prev) =&gt; ({ ...prev, fullNameError: '' }));
            return true;
          }
          break;
        case 'email':
          if (!/\S+@\S+\.\S+/.test(email)) {
            setState((prev) =&gt; ({ ...prev, emailError: 'err' }));
            return false;
          } else {
            setState((prev) =&gt; ({ ...prev, emailError: '' }));
            return true;
          }
          break;
        default:
          if (!/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/.test(password)) {
            setState((prev) =&gt; ({ ...prev, passwordError: 'err' }));
            return false;
          } else {
            setState((prev) =&gt; ({ ...prev, passwordError: '' }));
            return true;
          }
      }
    };
  
    return (
      &lt;div className='join'&gt;
        &lt;h2&gt;JOIN&lt;/h2&gt;
        &lt;h3&gt;some subheading&lt;/h3&gt;
        &lt;form onSubmit={onSubmit}&gt;
          &lt;label&gt;Name&lt;/label&gt;
          &lt;input
            type='text'
            placeholder='Full name'
            id='fullName'
            value={fullName}
            onChange={onChange}
            onBlur={onBlur}
          /&gt;
          {fullNameError}
          &lt;label&gt;Email&lt;/label&gt;
          &lt;input
            type='text'
            placeholder='Email address'
            id='email'
            value={email}
            onChange={onChange}
            onBlur={onBlur}
          /&gt;
          {emailError}
          &lt;label&gt;Password&lt;/label&gt;
          &lt;input
            type='password'
            placeholder='Create a password'
            id='password'
            value={password}
            onChange={onChange}
            onBlur={onBlur}
          /&gt;
          {passwordError}
          &lt;button color='primary'&gt;
            {!state.loading ? (
              'Join Now'
            ) : (
              &lt;img src={loadingImg} alt='loadingd' className='loading' /&gt;
            )}
          &lt;/button&gt;
          &lt;div className='join--terms'&gt;
            By joining, you agree to our
            &lt;Link to={{ pathname: '/terms' }}&gt; Terms of Service&lt;/Link&gt; and
            &lt;Link to={{ pathname: '/terms' }}&gt; Privacy Policy&lt;/Link&gt;
          &lt;/div&gt;
        &lt;/form&gt;
      &lt;/div&gt;
    );
  };
  
  export { Join };
  
  </code></pre>