Reputation: 802
on first button press onChange method function is called but state is not updating as it should and on second button press it is updating see this
import React,{useState} from 'react';
function MainHeader(props) {
const [FirstName, setFirstName] = useState('')
const [User, setUser] = useState({
FirstName: '',
LastName: ''
})
const nameOnChange = (event) => {
setFirstName(event.target.value)
console.log(FirstName)
}
const addName = () => {
setUser({
...User,
FirstName: FirstName
})
console.log(User)
props.addUserToFirebase(User)
}
return (
<div>
<h1>Checking</h1>
<input type="text" onChange={(e) => nameOnChange(e)} value={FirstName} />
<button onClick={() => addName()}>Enter</button>
</div>
);
}
on nameOnChange it is console.log(FirstName) when first time a pressed something then console logs empty state (initial state) and on second button it updates the previous button pressed. I have tried creating class component as well but i am seeing the same issue , same thing happens in the addName function it updates state on second click .
see console
Upvotes: 1
Views: 491
Reputation: 6512
https://reactjs.org/docs/hooks-effect.html
You must use useEffect()
.
const nameOnChange = (event) => {
setFirstName(event.target.value)
}
useEffect(()=>{
if(FirstName !== ''){
console.log(FirstName)
}
}, [FirstName])
const addName = () => {
setUser({
...User,
FirstName: FirstName
})
}
useEffect(()=>{
if(User.FirstName !== '' && User.LastName !== ''){
console.log(User)
props.addUserToFirebase(User)
}
}, [User])
Upvotes: 1
Reputation: 3604
I don't see a problem here. It is working perfectly as it should be. But the only problem I see is your wrong understanding of how React works or how Functional Programming works in general.
There's no mutation in Functional Programming
const nameOnChange = (event) => {
// event => new value
// FirstName => old value
// they remain that way throughout this function call
setFirstName(event.target.value)
// even if you set the state, the values won't change
// they will be updated only in next function call
console.log(FirstName) // still old value
}
The same goes for addName()
For each re-render React call the function MainHeader
with values that will not be mutated throughout their call or life. When value are updated, React will call MainHeader
with the updated the values.
Works, but not better way
const addName = () => {
setUser({
...User,
FirstName: FirstName
})
//
console.log({
...User,
FirstName: FirstName
}) // new value, since User is not mutated, User will still have the old value
props.addUserToFirebase(({
...User,
FirstName: FirstName
})
}
Better way
Always use useEffects for side effects.
// Just set the state
const addName = () => {
setUser({
...User,
FirstName: FirstName
})
}
// handle side effects here
useEffect(() => {
// check is needed here, since it will be
// called on component's first mount
if(User.FirstName !== ''){
console.log(User)
props.addUserToFirebase(User)
}
}, [User])
// This will be called whenever React detects a change in `User`
Upvotes: 2