在嵌套对象中,在React with Hooks中更新状态的正确方法是什么?

export Example = () => {
  const [exampleState, setExampleState] = useState(
  {masterField: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b"
           fieldTwoTwo: "c"
           }
        }
   })

如何使用setExampleState将exampleState更新为a(附加字段)?

const a = {
masterField: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b",
           fieldTwoTwo: "c"
           }
        },
  masterField2: {
        fieldOne: "c",
        fieldTwo: {
           fieldTwoOne: "d",
           fieldTwoTwo: "e"
           }
        },
   }
}

b(改变值)?

const b = {masterField: {
        fieldOne: "e",
        fieldTwo: {
           fieldTwoOne: "f"
           fieldTwoTwo: "g"
           }
        }
   })

当前回答

谢谢Philip,这帮助了我-我的用例是我有一个有很多输入字段的表单,所以我保持初始状态为对象,我不能更新对象状态。上面的帖子帮助了我:)

const [projectGroupDetails, setProjectGroupDetails] = useState({
    "projectGroupId": "",
    "projectGroup": "DDD",
    "project-id": "",
    "appd-ui": "",
    "appd-node": ""    
});

const inputGroupChangeHandler = (event) => {
    setProjectGroupDetails((prevState) => ({
       ...prevState,
       [event.target.id]: event.target.value
    }));
}

<Input 
    id="projectGroupId" 
    labelText="Project Group Id" 
    value={projectGroupDetails.projectGroupId} 
    onChange={inputGroupChangeHandler} 
/>


其他回答

你可以像这样传递新值:

  setExampleState({...exampleState,  masterField2: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b",
           fieldTwoTwo: "c"
           }
        },
   })

,就像这个例子:

首先创建对象的状态:

const [isSelected, setSelection] = useState([{ id_1: false }, { id_2: false }, { id_3: false }]);

然后更改它们的值:

// if the id_1 is false make it true or return it false.

onValueChange={() => isSelected.id_1 == false ? setSelection([{ ...isSelected, id_1: true }]) : setSelection([{ ...isSelected, id_1: false }])}

2022年

如果您正在寻找与此相同的功能。函数组件中的setState(来自类组件),那么这是对您有很大帮助的答案。

例如

你有一个像下面这样的状态,想要从整个状态中更新特定的字段,那么你需要每次都使用对象解构,有时它会令人恼火。

const [state, setState] = useState({first: 1, second: 2});

// results will be state = {first: 3} instead of {first: 3, second: 2}
setState({first: 3})

// To resolve that you need to use object destructing every time
// results will be state = {first: 3, second: 2}
setState(prev => ({...prev, first: 3}))

为了解决这个问题,我提出了useReducer方法。请检查useReducer。

const stateReducer = (state, action) => ({
  ...state,
  ...(typeof action === 'function' ? action(state) : action),
});
const [state, setState] = useReducer(stateReducer, {first: 1, second: 2});

// results will be state = {first: 3, second: 2}
setState({first: 3})

// you can also access the previous state callback if you want
// results will remain same, state = {first: 3, second: 2}
setState(prev => ({...prev, first: 3}))

您可以将该stateReducer存储在utils文件中,如果需要,也可以将其导入到每个文件中。

如果你需要,这里是自定义钩子。

import React from 'react';

export const stateReducer = (state, action) => ({
  ...state,
  ...(typeof action === 'function' ? action(state) : action),
});

const useReducer = (initial, lazyInitializer = null) => {
  const [state, setState] = React.useReducer(stateReducer, initial, init =>
    lazyInitializer ? lazyInitializer(init) : init
  );

  return [state, setState];
};

export default useReducer;

打印稿

import React, { Dispatch } from "react";

type SetStateAction<S> = S | ((prev: S) => S);

type STATE<R> = [R, Dispatch<SetStateAction<Partial<R>>>];

const stateReducer = (state, action) => ({
  ...state,
  ...(typeof action === "function" ? action(state) : action),
});

const useReducer = <S>(initial, lazyInitializer = null): STATE<S> => {
  const [state, setState] = React.useReducer(stateReducer, initial, (init) =>
    lazyInitializer ? lazyInitializer(init) : init,
  );

  return [state, setState];
};

export default useReducer;

答案已经有了,但是这种类型没有被提到,所以看看这种类型的例子…

 const[data,setdata]= useState({
    username: [
      email,
      "required", 
      //...some additional codes
    ],
    password: [
      password,
      "required|password-5",
     //..additional code if any..
    ],
  })

**要在输入字段中更新状态变量email,您可以添加类似的代码与您的变量名**

          <Input
              onChangeText={(t) => setdata(prevState=>({...prevState,username:{[0]:t}}))}
              value={data.username[0]}
            />

我已经给出了两个追加,整个对象更新,具体的关键更新的解决方案的例子

追加和修改都可以通过一个简单的步骤来完成。我认为这是更稳定和安全的,没有不可变或可变的依赖。

这就是追加新对象的方法

setExampleState(prevState => ({
    ...prevState,
    masterField2: {
        fieldOne: "c",
        fieldTwo: {
            fieldTwoOne: "d",
            fieldTwoTwo: "e"
        }
    },
}))

假设您想再次修改masterField2对象。可能有两种情况。您想要更新整个对象或更新对象的特定键。

更新整个对象-这里masterField2键的整个值将被更新。

setExampleState(prevState => ({
    ...prevState,
    masterField2: {
        fieldOne: "c",
        fieldTwo: {
            fieldTwoOne: "d",
            fieldTwoTwo: "e"
        }
    },
}))

但是如果你只想改变masterField2对象中的fieldTwoOne键呢?你可以这样做。

let oldMasterField2 = exampleState.masterField2
oldMasterField2.fieldTwo.fieldTwoOne = 'changed';
setExampleState(prevState => ({
    ...prevState,
    masterField2: oldMasterField2
}))