-1

this is my code,

    const [state, setState] = useState({
        email: '',
        password: '',
        last_name: '',
        first_name: ''
    });

    const emailChangeHandler = (e) => {
        setState(c => {
            return {
                ...c,
                email: e.target.value
            }
        })
    }

    return (
        <form>
            <input className="input" type="text" name="email" onChange={emailChangeHandler}/>
            <input className="input" type="text"/>
            <input className="input" type="text"/>
        </form>
    )

I'm trying to update the state when the input value is changed.

But error "TypeError: Cannot read property 'value' of null",

  13 |     setState(c => {
  14 |         return {
  15 |             ...c,
> 16 |             email: e.target.value
  17 | ^       }
  18 |     })
  19 | }

so, I'm trying to update state without the current state, like this:

const emailChangeHandler = (e) => {
    setState({...state, email: e.target.value})
}

and its work, but why? whats is the difference between setstate with currentstate and without currentstate?

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Zulfikar Ahmad
  • 407
  • 1
  • 7
  • 18
  • 1
    React reuses the event objects, so when it is called in the `setState` callback function, the event is no longer available. You could just put the value into a variable before. `const { value } = e.target; setState(s => ({ ...s, email: value });` – Emile Bergeron Apr 30 '20 at 04:57
  • As for the difference, there's a good question already: [When to use React setState callback](https://stackoverflow.com/q/48209452/1218980) – Emile Bergeron Apr 30 '20 at 05:00
  • @EmileBergeron Thank you very much, its work. I think i will read about SyntheticEvent now. – Zulfikar Ahmad Apr 30 '20 at 05:52

2 Answers2

1

If you use the setState callback the event values are cleared by react before it. So you need to store the values before using

   const email = e.target.value;
   setState(c => {
        return {
            ...c,
            email,
        }
    })

As far is difference between callback and without callbcak is concerned, State updates are batched and hence you use functional setState i.e setState with callback it is guranteed that the values will be from previous update even if multiple setState calls are made in the same event handler

For example

const emailChangeHandler = (e) => {
        setState({
                ...c,
                email: [...c.email,e.target.value]
            })
        setState({
                ...c,
                email: [...c.email, 'psw']
            })
    }

In the above case if c was {email: ['xyz@g.com'], name: 'p'}, post the update the value would become {email: ['xyz@g.com', 'psw'], name: 'p'} and not {email: ['xyz@g.com', e.target.value, 'psw'], name: 'p'}

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
0
This will work:

const emailChangeHandler = (e) => {
    const value = event.target.value;
    setState(c => {
        return {
            ...c,
            email: value
        }
    })
}

So here we are trying to use e.target.value in a closure, and closure basically locks the event object for the subsequent key strokes.

About React Events:
React Events are special synthetic events which replicates the native dom events

React basically re-uses these events objects and in our case also it will re-use the previous event object, hence we face the issue.

Prabhat Mishra
  • 951
  • 2
  • 12
  • 33