setState为嵌套对象的删除值

时间:2020-04-01 00:13:14

标签: reactjs

我处于以下状态:

const [state, setState] = React.useState({
    title: "",
    exchangeTypes: [],
    errors: {
        title: "",
        exchangeTypes: "",
      }
})

如果不遵守条件,我正在使用表单验证来填充state.errors对象。

function formValidation(e){
    const { name, value } = e.target;
    let errors = state.errors;

    switch (true) {
      case (name==='title' && value.length < 4): 
        setState(prevState => ({
            errors: {                            // object that we want to update
                ...prevState.errors,             // keep all other key-value pairs
                [name]: 'Title cannot be empty' // update the value of specific key
            }
        }))
        break;
      default:
        break;
    }

  }

这样做时,对象确实会更新,但是会删除我尚未更新的值。

在我调用formValidation之前 我的console.log(state)是:

{
    "title": "",
    "exchangeTypes: [],
    "errors": {
            title: "",
            exchangeTypes: "",
    }
}

我致电formValidation 之后 我的console.log(state)是:

{
    "errors": {
            title: "Title cannot be empty",
            exchangeTypes: ""
        }
}

SO 我的其他state值已消失。只有errors对象。

我遵循了本指南:How to update nested state properties in React

我想要什么:

{
    "title": "",
    "exchangeTypes: [],
    "errors": {
            title: "Title cannot be empty",
            exchangeTypes: "",
    }
}

我得到的是

   {
        "errors": {
                title: "Title cannot be empty",
                exchangeTypes: "",
        }
    }

2 个答案:

答案 0 :(得分:2)

与类组件中的setState不同,当您使用对象作为值时,通过useState的setState不会自动合并。您必须手动完成

setState((prevState) => ({
  ...prevState, // <- here
  errors: {
    // object that we want to update
    ...prevState.errors, // keep all other key-value pairs
    [name]: 'Title cannot be empty', // update the value of specific key
  },
}));

答案 1 :(得分:1)

尽管您当然可以按照自己的方式使用useState钩子,但更常见的约定是分别跟踪组件状态的各个部分。这是因为const MyComponent = () => { const [title, setTitle] = useState(''); const [exchangeTypes, setExchangeTypes] = useState([]); const [errors, setErrors] = useState({ title: "", exchangeTypes: "", }); function formValidation(e) { const { name, value } = e.target; switch (true) { case (name === 'title' && value.length < 4): setErrors({ ...errors, [name]: 'Title cannot be empty' }); break; default: break; } } return ( ... ); }; 取代了状态,而不是像您发现的那样将其合并。

来自React docs

您不必使用很多状态变量。状态变量可以很好地容纳对象和数组,因此您仍然可以将相关数据分组在一起。但是,与类中的this.setState不同,更新状态变量总是替换它而不是合并它。

因此,实际上,您的代码可能如下所示:

type