Reputation: 8646
I have below code :
import React,{useState} from 'react'
const iState ={
Name : '',
Email :'',
Salary :0,
Error:{
EName:'*',
EEmail:'*',
ESalary:'*'
}
}
function ReactForm() {
const [state, setstate] = useState(iState);
function validationHandler(e)
{
switch (e.target.name) {
case 'txtName':
console.log(e.target.value);
if(e.target.value=='')
{
console.log('inside condition')
setstate({...state.Error, EName:'Value Cannot be blank'})
console.log(state);
}
else
{
console.log('inside else condition')
setstate({...state, EName:''})
}
setstate({...state, Name:e.target.value})
break;
case 'txtEmail':
setstate({...state, Email:e.target.value})
break;
case 'txtSalary':
setstate({...state, Salary:e.target.value})
break;
default:
break;
}
console.log(state);
}
return (
<div>
Name : <input name="txtName" type="text" onChange={(e)=>validationHandler(e)}></input>
<label> {state.Error.EName==undefined ? '*':state.Error.EName} </label>
<br></br>
Email : <input name="txtEmail" type="text" onChange={(e)=>validationHandler(e)}></input>
<br></br>
Salary : <input name="txtSalary" type="text" onChange={(e)=>validationHandler(e)}></input>
<br></br>
<button onClick={validationHandler}>Validate Us</button>
</div>
)
}
export default ReactForm
In this, iState has Error portion nested within -
const iState ={
Name : '',
Email :'',
Salary :0,
Error:{
EName:'*',
EEmail:'*',
ESalary:'*'
}
}
When I am trying to update the nested state of Error , its not getting updated -
if(e.target.value=='')
{
console.log('inside condition')
setstate({...state.Error, EName:'Value Cannot be blank'})
console.log(state);
}
else
{
console.log('inside else condition')
setstate({...state, EName:''})
}
I can see it entering within else block , but not updating the state.
I also tried with - setstate({...state.Error, EName:''})
EDIT 1 :
if(e.target.value=='')
{
console.log('inside condition')
setstate({ ...state, Error: { ...state.Error, Ename: 'Value Cannot be blank' }})
console.log(state);
}
else
{
console.log('inside else condition')
setstate({ ...state, Error: { ...state.Error, Ename: 'Value Cannot be blank' }})
}
Setting state changed -setstate({ ...state, Error: { ...state.Error, Ename: 'Value Cannot be blank' }})
Still state not getting updated -
Upvotes: 3
Views: 115
Reputation: 29344
Unlike this.setState
in class components, state setter function returned by the useState
hook does not merges the old state with the new state - you need to do it yourself. Not doing this will overwrite the existing state.
Currently you are overwriting the existing state. Correct way to update the state is shown below:
This
setstate({...state.Error, EName:'Value Cannot be blank'})
should be
setstate({ ...state, Error: { ...state.Error, Ename: 'Value Cannot be blank' } })
Explanation of why this works:
First you spread the top level state object in the newly created object passed to setState
. After that you add Error
key and its value is another object in which you spread state.Error
. Finally, you add a Ename
key in the nested object and set its value.
Above steps re-create a new object with the similar structure as the initial state object.
Similarly this
setstate({...state, EName:''})
should be
setstate({...state, Error: { ...state.Error, EName:'' } })
Please note that state is updated asynchronously and it is constant within a particular render of a component.
This means that logging the state immediately after calling the state setter function will log the old state. Component can only see the updated state after it has re-rendered.
To log the updated state, use the useEffect
hook as shown below:
useEffect(() => {
console.log(state);
}, [state]);
This will log the updated state because it will execute:
state
update.Upvotes: 1
Reputation: 208
You have to use spread current state and update the nested vaues
setState( previous => {...previous, Error: { ...previous.Error, EName:'Value Cannot be blank'} })
Upvotes: 1
Reputation: 2695
You shouldn't use the previous state directly while setting the new state as state changes are asynchronous.
setState((prevState)=>{...prevState, Error: { ...prevState.Error, EName:'Value Cannot be blank' }})
Upvotes: 2
Reputation: 895
You should make it like this
setstate({...state, Error: { ...state.Error, EName:'Value Cannot be blank' }})
Upvotes: 1