Javascript 此.setState不是';我不能像我所期望的那样合并各州
我有以下情况:Javascript 此.setState不是';我不能像我所期望的那样合并各州,javascript,reactjs,Javascript,Reactjs,我有以下情况: this.setState({ selected: { id: 1, name: 'Foobar' } }); 然后我更新状态: this.setState({ selected: { name: 'Barfoo' }}); 由于setState被假定为合并,我希望它是: { selected: { id: 1, name: 'Barfoo' } }; 但它会吃掉id,状态是: { selected: { name: 'Barfoo' } }; 这是预期的行为吗?
this.setState({ selected: { id: 1, name: 'Foobar' } });
然后我更新状态:
this.setState({ selected: { name: 'Barfoo' }});
由于setState
被假定为合并,我希望它是:
{ selected: { id: 1, name: 'Barfoo' } };
但它会吃掉id,状态是:
{ selected: { name: 'Barfoo' } };
这是预期的行为吗?仅更新嵌套状态对象的一个属性的解决方案是什么?我认为setState()
不执行递归合并
您可以使用当前状态的值this.state.selected
构造一个新状态,然后对该状态调用setState()
:
var newSelected = _.extend({}, this.state.selected);
newSelected.name = 'Barfoo';
this.setState({ selected: newSelected });
在这里,我使用了函数\uuu.extend()
函数(来自underline.js库),通过创建状态的浅层副本来防止对现有的选定的
部分进行修改
另一种解决方案是编写setStateRecursive()
,它在新状态上进行递归合并,然后用它调用replaceState()
:
setStateRecursively: function(stateUpdate, callback) {
var newState = mergeStateRecursively(this.state, stateUpdate);
this.replaceState(newState, callback);
}
你设置好初始状态了吗 我将使用我自己的一些代码,例如:
getInitialState: function () {
return {
dragPosition: {
top : 0,
left : 0
},
editValue : "",
dragging : false,
editing : false
};
}
在我正在开发的一个应用程序中,我就是这样设置和使用状态的。我相信在setState
上,你可以编辑你想要的任何状态,我一直这样称呼它:
onChange: function (event) {
event.preventDefault();
event.stopPropagation();
this.setState({editValue: event.target.value});
},
请记住,您必须在调用的
getInitialState
不可变帮助程序最近添加到React.addons的React.createClass
函数中设置状态,这样,您现在可以执行以下操作:
var newState = React.addons.update(this.state, {
selected: {
name: { $set: 'Barfoo' }
}
});
this.setState(newState);
.我使用tmp变量进行更改
changeTheme(v) {
let tmp = this.state.tableData
tmp.theme = v
this.setState({
tableData : tmp
})
}
对于这种情况,我的解决方案是使用,就像另一个答案指出的那样 由于深入设置状态是一种常见情况,我创建了以下mixin:
var SeStateInDepthMixin = {
setStateInDepth: function(updatePath) {
this.setState(React.addons.update(this.state, updatePath););
}
};
这个mixin包含在我的大多数组件中,我通常不再直接使用setState
使用此mixin,要达到预期效果,只需按以下方式调用函数setStateinDepth
:
setStateInDepth({ selected: { name: { $set: 'Barfoo' }}})
有关更多信息:
- 有关混合器在React中的工作方式,请参见
- 关于传递给
的参数的语法,请参见不变性帮助程序setStateinDepth
getInitialState: function () {
return {
dragPosition: {
top : 0,
left : 0
},
editValue : "",
dragging : false,
editing : false
};
}
如果需要使用当前状态(例如,将数据合并到嵌套对象中),setState也可以接受函数作为参数而不是对象;该函数在之前对状态进行任何更新后调用,并将状态作为参数传递——因此可以使用该函数进行原子更改,以保证尊重以前的更改。我使用的是es6类,我的顶层状态有几个复杂的对象,并试图使我的主组件更加模块化,因此,我创建了一个简单的类包装器,将状态保留在顶部组件上,但允许更多的本地逻辑 包装器类将函数作为其构造函数,该构造函数在主组件状态上设置属性
export default class StateWrapper {
constructor(setState, initialProps = []) {
this.setState = props => {
this.state = {...this.state, ...props}
setState(this.state)
}
this.props = initialProps
}
render() {
return(<div>render() not defined</div>)
}
component = props => {
this.props = {...this.props, ...props}
return this.render()
}
}
导出默认类StateWrapper{
构造函数(setState,initialProps=[]){
this.setState=props=>{
this.state={…this.state,…props}
setState(this.state)
}
this.props=初始值props
}
render(){
返回(render()未定义)
}
组件=道具=>{
this.props={…this.props,…props}
返回这个
}
}
然后,对于顶部状态上的每个复杂属性,我创建一个StateWrapped类。您可以在这里的构造函数中设置默认的道具,它们将在初始化类时设置,您可以参考本地状态获取值并设置本地状态,参考本地函数,并将其传递到链上:
class WrappedFoo extends StateWrapper {
constructor(...props) {
super(...props)
this.state = {foo: "bar"}
}
render = () => <div onClick={this.props.onClick||this.onClick}>{this.state.foo}</div>
onClick = () => this.setState({foo: "baz"})
}
类WrappedFoo扩展了StateWrapper{
构造函数(…props){
超级(…道具)
this.state={foo:bar}
}
render=()=>{this.state.foo}
onClick=()=>this.setState({foo:baz})
}
因此,我的顶级组件只需要构造函数将每个类设置为它的顶级状态属性、一个简单的呈现和任何跨组件通信的函数
class TopComponent extends React.Component {
constructor(...props) {
super(...props)
this.foo = new WrappedFoo(
props => this.setState({
fooProps: props
})
)
this.foo2 = new WrappedFoo(
props => this.setState({
foo2Props: props
})
)
this.state = {
fooProps: this.foo.state,
foo2Props: this.foo.state,
}
}
render() {
return(
<div>
<this.foo.component onClick={this.onClickFoo} />
<this.foo2.component />
</div>
)
}
onClickFoo = () => this.foo2.setState({foo: "foo changed foo2!"})
}
类TopComponent扩展了React.Component{
常数
this.setState((previousState) => _.merge({}, previousState, { selected: { name: "Barfood"} }), () => alert(this.state.selected));
import update from "react-addons-update";
this.setState((previousState) => update(previousState, {
selected:
{
name: {$set: "Barfood"}
}
});
this.linkAt( 'selected' ).at( 'name' ).set( 'Barfoo' );
this.setState({ selected: { name: 'Barfoo' }});
var newSelected = Object.assign({}, this.state.selected);
newSelected.name = 'Barfoo';
this.setState({ selected: newSelected });
this.setState({ selected: Object.assign({}, this.state.selected, { name: "Barfoo" }) });
this.setState((prevState) => {
return {quantity: prevState.quantity + 1};
});
this.setState(prevState => {
var newSelected = JSON.parse(JSON.stringify(prevState.selected)) //1
newSelected.name = 'Barfoo'; //2
var update = { selected: newSelected }; //3
return update; //4
});
this.setState(prevState => {
var selected = JSON.parse(JSON.stringify(prevState.selected)) //1
selected.name = 'Barfoo'; //2
return { selected }; //3, 4
});
this.setState({ selected: { id: 1, name: 'Foobar' } });
//this.state: { selected: { id: 1, name: 'Foobar' } }
const { selected: _selected } = this.state
const selected = { ..._selected, name: 'Barfoo' }
this.setState({selected})
//this.state: { selected: { id: 1, name: 'Barfoo' } }