我尝试使用React进行实验,我遇到了更新特定密钥的状态值的问题。
这是我的州
this.state = {
connections : {
facebook : "http://facebook.com",
flickr : null,
foursquare : null,
googleplus : null,
id : 0,
instagram : "http://instagram.com/",
openstreetmap : null,
pinterest : null,
place_id : 1,
tomtom : null,
tripadvisor : null,
twitter : "http://twitter.com",
vimeo : null,
wikipedia : null,
yelp : null,
youtube : null
},
contact : {
}
}
我正在调用外部组件并向其发送参数。
<Connection type="Facebook" icon={facebookIcon} placeholder="Add Facebook Link" name="facebook" value={this.state.connections.facebook} onChange={this.handleChange.bind(this)}/>
<Connection type="Twitter" icon={twitterIcon} placeholder="Add Twitter Link" name="twitter" value={this.state.connections.twitter} onChange={this.handleChange.bind(this)}/>
<Connection type="Instagram" icon={instagramIcon} placeholder="Add Instagram Link" name="instagram" value={this.state.connections.instagram} onChange={this.handleChange.bind(this)}/>
外部文件中的组件:
<input type="text" name={this.props.name} placeholder={this.state.placeholder} value={this.props.value} onChange={this.props.onChange} />
关于文本框中值的更改,
handleChange(e) {
this.setState({
connections : {[e.target.name]: e.target.value}
})
}
当我尝试更改任何字段值时,它会将其余2设置为空。例如,如果我尝试编辑Facebook的文本框,它会将Twitter和Instagram值设置为空。
我可以知道在设置handleChange时我做错了什么吗?我确定 this.setState 有问题,但不确定如何定位特定键值。
答案 0 :(得分:10)
在这种情况下,您需要获取以前的状态并创建新的(对于合并状态,您可以使用Object.assign
,传播运算符...
或lodash merge
) ,因为setState
,
执行nextState到当前状态的浅层合并。
this.setState({
connections: Object.assign(
{},
this.state.connections,
{ [e.target.name]: e.target.value }
),
contact: {}
});
实施例
class Connection extends React.Component {
render() {
return <input
type="text"
placeholder={this.props.placeholder}
name={this.props.name}
value={this.props.value}
onChange={this.props.onChange} />
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
connections : {
facebook : "http://facebook.com",
flickr : null,
foursquare : null,
googleplus : null,
id : 0,
instagram : "http://instagram.com/",
openstreetmap : null,
pinterest : null,
place_id : 1,
tomtom : null,
tripadvisor : null,
twitter : "http://twitter.com",
vimeo : null,
wikipedia : null,
yelp : null,
youtube : null
},
contact: {}
}
}
handleChange(e) {
this.setState({
connections: Object.assign(
{},
this.state.connections,
{ [e.target.name]: e.target.value }
),
contact: {}
})
}
render() {
return (
<div>
<Connection
type="Facebook"
placeholder="Add Facebook Link"
name="facebook"
value={this.state.connections.facebook}
onChange={this.handleChange.bind(this)}
/>
<Connection
type="Twitter"
placeholder="Add Twitter Link"
name="twitter"
value={this.state.connections.twitter}
onChange={this.handleChange.bind(this)}
/>
<Connection
type="Instagram"
placeholder="Add Instagram Link"
name="instagram"
value={this.state.connections.instagram}
onChange={this.handleChange.bind(this)}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
&#13;
答案 1 :(得分:4)
setState
执行浅合并而不是深度合并(the docs中的更多解释),因此您只需使用一个值完全覆盖所有connections
。如果您希望connections
中的其他密钥保持不变,可以将handleChange
更改为:
handleChange(e) {
this.setState({
connections : {...this.state.connections, [e.target.name]: e.target.value}
})
}
这将对所有this.state.connections
进行浅层复制,然后将e.target.name
设置在其上方。
答案 2 :(得分:1)
你是对的,问题在于你的setState。
handleChange(e) {
this.setState({
connections : {[e.target.name]: e.target.value} //this will trigger twitter and instagram with empty value.
})
}
一个简单的解决方法是:
handleChange(e) {
this.setState({
connections : {[e.target.name]: e.target.value, twitter: 'initial val', instagram: 'initial val'}
})
}
答案 3 :(得分:0)
您实际上应该宁愿使用
handleChange(e) {
this.setState(oldState => ({
connections: {[e.target.name]: e.target.value, ...oldState.connections},
}));
}
因为否则您可能会覆盖尚未应用的状态更改。