我试图通过使用这样的嵌套属性来组织我的状态:
this.state = {
someProperty: {
flag:true
}
}
但是像这样更新状态,
this.setState({ someProperty.flag: false });
是行不通的。怎样才能正确地做到这一点呢?
我试图通过使用这样的嵌套属性来组织我的状态:
this.state = {
someProperty: {
flag:true
}
}
但是像这样更新状态,
this.setState({ someProperty.flag: false });
是行不通的。怎样才能正确地做到这一点呢?
当前回答
我看到每个人都给出了基于类的组件状态更新解决方案,这是预期的,因为他要求,但我试图给钩子相同的解决方案。
const [state, setState] = useState({
state1: false,
state2: 'lorem ipsum'
})
现在,如果你想改变嵌套对象键state1,那么你可以做以下任何一项:
过程1
let oldState = state;
oldState.state1 = true
setState({...oldState);
流程2
setState(prevState => ({
...prevState,
state1: true
}))
我最喜欢过程。
其他回答
用于多个输入控件和动态嵌套名称
<input type="text" name="title" placeholder="add title" onChange={this.handleInputChange} />
<input type="checkbox" name="chkusein" onChange={this.handleInputChange} />
<textarea name="body" id="" cols="30" rows="10" placeholder="add blog content" onChange={this.handleInputChange}></textarea>
代码非常易读
处理程序
handleInputChange = (event) => {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
const newState = { ...this.state.someProperty, [name]: value }
this.setState({ someProperty: newState })
}
你应该把new state传递给setState。 新状态的引用必须与旧状态的引用不同。
所以试试这个:
this.setState({
...this.state,
someProperty: {...this.state.someProperty, flag: true},
})
免责声明
React中的嵌套状态是错误的设计 阅读这篇精彩的回答。
这个答案背后的原因是: React的setState只是一个内置的方便,但你很快就会意识到 它有它的局限性。使用自定义属性和智能使用 forceUpdate提供更多信息。 例如: MyClass扩展React。组件{ myState = someObject inputValue = 42 … 例如,MobX完全抛弃状态,使用自定义可观察属性。 在React组件中使用observable而不是state。
你痛苦的答案——请看这里的例子
还有另一种更短的方法来更新任何嵌套的属性。
this.setState(state => {
state.nested.flag = false
state.another.deep.prop = true
return state
})
在一行上
this.setState(state => (state.nested.flag = false, state))
注意:这里是逗号操作符~MDN,在这里(沙盒)看到它的作用。
它类似于(尽管这不会改变状态引用)
this.state.nested.flag = false
this.forceUpdate()
关于这个上下文中forceUpdate和setState之间的细微差别,请参阅链接示例和沙盒。
当然,这是在滥用一些核心原则,因为状态应该是只读的,但是由于您立即丢弃了旧状态并用新状态替换它,所以这是完全可以的。
警告
即使包含状态的组件将正确更新和重新渲染(除了这个gotcha),道具将无法传播给孩子(见Spymaster的评论下面)。只有当你知道你在做什么时才使用这个技巧。
例如,您可以传递一个已更改的平面道具,该道具已更新并易于传递。
render(
//some complex render with your nested state
<ChildComponent complexNestedProp={this.state.nested} pleaseRerender={Math.random()}/>
)
现在即使complexNestedProp的引用没有改变(shouldComponentUpdate)
this.props.complexNestedProp === nextProps.complexNestedProp
每当父组件更新时,组件都会重新呈现,这是在调用this之后的情况。setState或this。在父类中执行forceUpdate。
改变状态沙箱的效果
使用嵌套状态和直接改变状态是危险的,因为不同的对象可能(有意或无意地)持有对状态的不同(旧的)引用,并且可能不一定知道何时更新(例如使用PureComponent时,或者如果shouldComponentUpdate被实现以返回false)或意图显示旧数据,如下例所示。
想象一下,一个应该呈现历史数据的时间轴,改变手上的数据将导致意想不到的行为,因为它也会改变之前的项目。
无论如何,在这里你可以看到嵌套的PureChildClass没有被重新渲染,因为道具未能传播。
试试下面的代码:
this.setState({ someProperty: {flag: false} });
setInputState((pre)=> ({...pre,[parentKey]: {...pre[parentKey], [childKey]: value}}));
我喜欢这个