React - 仅对特定键的状态更新值

Dee*_*ndi 9 javascript ecmascript-6 reactjs react-redux

我正在尝试使用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 : {

        }
    }
Run Code Online (Sandbox Code Playgroud)

我正在调用外部组件并向其发送参数.

<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)}/>
Run Code Online (Sandbox Code Playgroud)

外部文件中的组件:

<input type="text" name={this.props.name} placeholder={this.state.placeholder} value={this.props.value} onChange={this.props.onChange} />
Run Code Online (Sandbox Code Playgroud)

关于文本框中的值的变化,

handleChange(e) {        
    this.setState({
        connections : {[e.target.name]: e.target.value}
    })
}
Run Code Online (Sandbox Code Playgroud)

当我尝试更改任何字段值时,它将其余的2设置为空.例如,如果我尝试编辑Facebook的文本框,它会将Twitter和Instagram值设置为空.

我可以知道在设置handleChange时我做错了什么吗?我确定this.setState有问题,但不确定如何定位特定的键值.

Ale*_* T. 12

在这种情况下,您需要获取以前的状态并创建新的(对于您可以使用的合并状态Object.assign,扩展运算符...或lodash merge),因为setState,

执行nextState到当前状态的浅合并.

this.setState({    
  connections: Object.assign(
    {}, 
    this.state.connections,
    { [e.target.name]: e.target.value }
  ),
  contact: {}
});
Run Code Online (Sandbox Code Playgroud)

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'));
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的解决方案.它工作得很好. (2认同)

Dre*_*ter 7

setState执行浅合并而不是深合并(文档中有更多解释),因此您connections仅用一个值就可以完全覆盖所有内容。如果你想保持其他键connections完好无损,你可以改成handleChange这样:

handleChange(e) {        
    this.setState({
        connections : {...this.state.connections, [e.target.name]: e.target.value}
    })
}
Run Code Online (Sandbox Code Playgroud)

这将浅复制所有this.state.connections,然后设置e.target.name在它之上。