javascript - React:使用 Hooks 为深度嵌套对象设置状态
问题描述
我正在使用 React 中深度嵌套的状态对象。我的代码库要求我们尝试使用函数组件,因此每次我想更新嵌套对象中的键/值对时,我都必须使用钩子来设置状态。不过,我似乎无法理解更深层次的嵌套项目。我有一个带有 onChange 处理程序的下拉菜单。. .inside onChange 处理程序是一个内联函数,用于直接设置任何正在更改的键/值对的值。
但是,我在每个内联函数中的展开运算符之后使用的语法是错误的。
作为一种解决方法,我已将内联函数分解为它自己的函数,该函数在每次状态更改时重写整个状态对象,但这非常耗时且丑陋。我宁愿像下面这样内联:
const [stateObject, setStateObject] = useState({
top_level_prop: [
{
nestedProp1: "nestVal1",
nestedProp2: "nestVal2"
nestedProp3: "nestVal3",
nestedProp4: [
{
deepNestProp1: "deepNestedVal1",
deepNestProp2: "deepNestedVal2"
}
]
}
]
});
<h3>Top Level Prop</h3>
<span>NestedProp1:</span>
<select
id="nested-prop1-selector"
value={stateObject.top_level_prop[0].nestedProp1}
onChange={e => setStateObject({...stateObject,
top_level_prop[0].nestedProp1: e.target.value})}
>
<option value="nestVal1">nestVal1</option>
<option value="nestVal2">nestVal2</option>
<option value="nestVal3">nestVal3</option>
</select>
<h3>Nested Prop 4</h3>
<span>Deep Nest Prop 1:</span>
<select
id="deep-nested-prop-1-selector"
value={stateObject.top_level_prop[0].nestprop4[0].deepNestProp1}
onChange={e => setStateObject({...stateObject,
top_level_prop[0].nestedProp4[0].deepNestProp1: e.target.value})}
>
<option value="deepNestVal1">deepNestVal1</option>
<option value="deepNestVal2">deepNestVal2</option>
<option value="deepNestVal3">deepNestVal3</option>
</select>
上面代码的结果给了我一个“nestProp1”和“deepNestProp1”是未定义的,大概是因为它们永远不会被每个选择器到达/改变它们的状态。我的预期输出将是与选择器当前 val 的值匹配的选定选项(在状态更改之后)。任何帮助将不胜感激。
解决方案
我认为您应该使用 的函数形式setState
,这样您就可以访问当前状态并对其进行更新。
喜欢:
setState((prevState) =>
//DO WHATEVER WITH THE CURRENT STATE AND RETURN A NEW ONE
return newState;
);
看看是否有帮助:
function App() {
const [nestedState,setNestedState] = React.useState({
top_level_prop: [
{
nestedProp1: "nestVal1",
nestedProp2: "nestVal2",
nestedProp3: "nestVal3",
nestedProp4: [
{
deepNestProp1: "deepNestedVal1",
deepNestProp2: "deepNestedVal2"
}
]
}
]
});
return(
<React.Fragment>
<div>This is my nestedState:</div>
<div>{JSON.stringify(nestedState)}</div>
<button
onClick={() => setNestedState((prevState) => {
prevState.top_level_prop[0].nestedProp4[0].deepNestProp1 = 'XXX';
return({
...prevState
})
}
)}
>
Click to change nestedProp4[0].deepNestProp1
</button>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
更新:带有下拉菜单
function App() {
const [nestedState,setNestedState] = React.useState({
propA: 'foo1',
propB: 'bar'
});
function changeSelect(event) {
const newValue = event.target.value;
setNestedState((prevState) => {
return({
...prevState,
propA: newValue
});
});
}
return(
<React.Fragment>
<div>My nested state:</div>
<div>{JSON.stringify(nestedState)}</div>
<select
value={nestedState.propA}
onChange={changeSelect}
>
<option value='foo1'>foo1</option>
<option value='foo2'>foo2</option>
<option value='foo3'>foo3</option>
</select>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
推荐阅读
- python - python SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX 转义错误
- django - 来自其他模型的用户评价数据
- html - 删除类后保留 CSS 变换属性
- javascript - 截图后谷歌地图cssRules问题
- javascript - 从for循环中的输入值创建JS变量
- python - 如何在热图中取消加粗颜色条标签
- vue.js - Vue 状态不与 kendo 数据源同步
- python - 在 wxpython 上,使用 Ctrl + A 选择所有项目或使用按钮选择项目
- javascript - konvajs 多点触控秤台
- python - 使用 pyscreenshot 仅抓取屏幕的一部分