简体   繁体   English

ReactJs:嵌套 State 未更新

[英]ReactJs : Nested State Not getting Updated

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 -在此,iState 有错误部分嵌套在 -

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 -当我尝试更新错误的嵌套 state 时,它没有得到更新 -

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.我可以看到它进入 else 块,但没有更新 state。 I also tried with - setstate({...state.Error, EName:''})我也试过 - setstate({...state.Error, EName:''})

EDIT 1:编辑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' }})设置 state 已更改 - setstate({...state, Error: {...state.Error, Ename: 'Value Cannot be blank' }})

Still state not getting updated -仍然 state 没有得到更新 -

在此处输入图像描述

You shouldn't use the previous state directly while setting the new state as state changes are asynchronous.您不应该直接使用以前的 state 而将新的 state 设置为 state 更改是异步的。

setState((prevState)=>{...prevState, Error: { ...prevState.Error, EName:'Value Cannot be blank' }})

You should make it like this你应该这样

setstate({...state, Error: { ...state.Error, EName:'Value Cannot be blank' }})

You have to use spread current state and update the nested vaues您必须使用传播电流 state 并更新嵌套值

setState( previous => {...previous, Error: { ...previous.Error, EName:'Value Cannot be blank'} })

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. 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.不这样做将覆盖现有的 state。

Currently you are overwriting the existing state.目前您正在覆盖现有的 state。 Correct way to update the state is shown below:更新 state 的正确方法如下所示:

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 .首先,在传递给setState的新创建的 object 中传播顶层 state object 。 After that you add Error key and its value is another object in which you spread state.Error .之后,您添加Error键,其值是另一个 object 您在其中传播state.Error Finally, you add a Ename key in the nested object and set its value.最后,在嵌套的 object 中添加一个Ename键并设置其值。

Above steps re-create a new object with the similar structure as the initial state object.上述步骤重新创建一个新的 object,其结构与初始 state object 类似。

Similarly this同样这个

setstate({...state, EName:''})

should be应该

setstate({...state, Error: { ...state.Error, EName:'' } })

Edit编辑

Please note that state is updated asynchronously and it is constant within a particular render of a component.请注意,state 是异步更新的,并且在组件的特定渲染中是恒定的。

This means that logging the state immediately after calling the state setter function will log the old state.这意味着在调用 state 设置器 function 后立即记录 state 将记录旧的 Z9ED39E25EA9312586B76E Component can only see the updated state after it has re-rendered.组件在重新渲染只能看到更新的 state。

To log the updated state, use the useEffect hook as shown below:要记录更新的 state,请使用useEffect挂钩,如下所示:

useEffect(() => {
  console.log(state);
}, [state]);

This will log the updated state because it will execute:这将记录更新的 state 因为它将执行:

  • after the initial render在初始渲染之后
  • every time component re-renders as a result of state update.每次组件由于state更新而重新渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM