React Hooks useState() 与 Object

IT技术 javascript reactjs react-hooks
2021-02-01 22:54:08

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

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

如何使用setExampleState更新exampleStatea(附加字段)?

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"
           }
        }
   })
6个回答

您可以像这样传递新值:

  setExampleState({...exampleState,  masterField2: {
        fieldOne: "a",
        fieldTwo: {
           fieldTwoOne: "b",
           fieldTwoTwo: "c"
           }
        },
   })
太好了,这回答了部分!你知道 b 部分的最佳实践吗?
2021-03-19 22:54:08
如果您使用与其 Dispatcher 相同的状态,则应该使用函数。 setExampleState( exampleState => ({...exampleState, masterField2: {...etc} }) );
2021-04-01 22:54:08
改变刚刚过去masterField而不是masterField2 setExampleState({...exampleState, masterField:{//新值}
2021-04-06 22:54:08
使用扩展运算符时请注意浅层复制。参见例如:stackoverflow.com/questions/43638938/...
2021-04-08 22:54:08

如果有人正在搜索 useState()挂钩更新对象

- Through Input

        const [state, setState] = useState({ fName: "", lName: "" });
        const handleChange = e => {
            const { name, value } = e.target;
            setState(prevState => ({
                ...prevState,
                [name]: value
            }));
        };

        <input
            value={state.fName}
            type="text"
            onChange={handleChange}
            name="fName"
        />
        <input
            value={state.lName}
            type="text"
            onChange={handleChange}
            name="lName"
        />
   ***************************

 - Through onSubmit or button click
    
        setState(prevState => ({
            ...prevState,
            fName: 'your updated value here'
         }));
为什么需要使用回调?
2021-03-18 22:54:08
@Yola这个答案提供了比我更好的解释。
2021-04-08 22:54:08

通常,您应该注意 React 状态中的深层嵌套对象。为了避免意外行为,状态应该不可变地更新。当您拥有深层对象时,您最终会深入克隆它们以实现不变性,这在 React 中可能非常昂贵。为什么?

一旦你深度克隆状态,React 将重新计算并重新渲染依赖于变量的一切,即使它们没有改变!

因此,在尝试解决您的问题之前,请先考虑如何使状态变平。一旦你这样做了,你就会找到有助于处理大状态的方便的工具,比如 useReducer()。

如果您考虑过,但仍然确信您需要使用深度嵌套的状态树,您仍然可以将 useState() 与诸如immutable.jsImmutability -helper 之类的库一起使用它们使更新或克隆深层对象变得简单,而不必担心可变性。

您还可以使用Hookstate(免责声明:我是作者)来管理复杂的(本地和全局)状态数据,而无需进行深度克隆,也无需担心不必要的更新——Hookstate 将为您处理。
2021-03-31 22:54:08

我参加聚会迟到了.. :)

当意图重新输入整个对象结构时,@aseferov 答案非常有效。但是,如果目标/目标是更新对象中的特定字段值,我相信下面的方法会更好。

情况:

const [infoData, setInfoData] = useState({
    major: {
      name: "John Doe",
      age: "24",
      sex: "M",
    },

    minor:{
      id: 4,
      collegeRegion: "south",

    }

  });

更新特定记录将需要召回之前的状态 prevState

这里:

setInfoData((prevState) => ({
      ...prevState,
      major: {
        ...prevState.major,
        name: "Tan Long",
      }
    }));

也许

setInfoData((prevState) => ({
      ...prevState,
      major: {
        ...prevState.major,
        name: "Tan Long",
      },
      minor: {
        ...prevState.minor,
        collegeRegion: "northEast"

    }));

我希望这可以帮助任何试图解决类似问题的人。

我有个问题。为什么我们需要将函数括在括号中?我不确定引擎盖下发生了什么。你会碰巧知道或者我可以在哪里阅读更多相关信息?
2021-03-26 22:54:08
非常有帮助,特别是对于您尝试更新嵌套数层深的属性的情况,即:first.second.third - 其他示例涵盖 first.second,但不包括 first.second.third
2021-04-01 22:54:08
@MichaelRamage 为什么我们将函数括在括号中::()简单地回答这个问题;这是因为setInfoData 本质上是高阶的,即它可以承担另一个功能作为参数,这要归功于 Hook 提供的功能:useState。我希望这篇文章能更清楚地说明高阶函数:sitepoint.com/higher-order-functions-javascript
2021-04-07 22:54:08

谢谢菲利普,这帮助了我 - 我的用例是我有一个包含很多输入字段的表单,所以我将初始状态保持为对象,但我无法更新对象状态。上面的帖子帮助了我:)

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} 
/>