2016-12-30 8 views
5

Ich versuche mit React zu experimentieren, habe ich ein Problem der Aktualisierung der Statuswerte eines bestimmten Schlüssels.React - State Update nur Wert von bestimmten Schlüssel

Hier ist mein Zustand

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 : { 

     } 
    } 

Ich bin eine externe Komponente aufrufen und Parameter, um es zu senden.

<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)}/> 

Komponente in externer Datei:

<input type="text" name={this.props.name} placeholder={this.state.placeholder} value={this.props.value} onChange={this.props.onChange} /> 

Auf Wertänderung in Textbox,

handleChange(e) {   
    this.setState({ 
     connections : {[e.target.name]: e.target.value} 
    }) 
} 

Während ich versuche, alle Feldwerte zu ändern, setzt er den Rest 2 mit leer. Wenn ich beispielsweise versuche, die Textbox von Facebook zu bearbeiten, werden die Werte für Twitter und Instagram auf leer gesetzt.

Darf ich wissen, was ich beim Einstellen von handleChange falsch mache? Ich bin sicher, es ist etwas falsch mit this.setState, aber nicht sicher, wie bestimmte Schlüsselwert Ziel.

+0

vor allem sollten Sie nicht so eine lange Liste von lokalen Zustand haben. Grund a) schwer zu handhaben 2) es bricht Code, wenn Sie versuchen, etwas zu ändern. Brechen Sie die große Komponente in eine kleinere Komponente. für dein Problem versuche, e.preventDefault in handleChange Funktion hinzuzufügen –

+0

@KhalidAzam Danke, dass du mich darüber informiert hast, ich sehe keine Möglichkeit, die Liste zu durchbrechen, hast du irgendwelche Tipps dazu?Coz, meine nächste Komponente sind Annehmlichkeiten, und es hat eine Liste, die 100 mal so groß ist. Ich habe mich gefragt, als externe js zu speichern und hier zu importieren. Irgendwelche besseren Ideen würden geschätzt werden. –

Antwort

8

In diesem Fall Sie vorherigen Zustand und neue erhalten müssen (merge heißt es können Sie Object.assign, Verbreitung Operator ... oder lodash merge verwenden) , weil setState,

Führt eine flache Zusammenführung von nextState in den aktuellen Status.

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

Beispiel

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'));
<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>

+1

Danke für die Lösung. Es funktioniert vollkommen in Ordnung. –

1

Sie haben Recht, das Problem ist mit Ihrem SetState.

handleChange(e) {   
    this.setState({ 
     connections : {[e.target.name]: e.target.value} //this will trigger twitter and instagram with empty value. 
    }) 
} 

Eine einfache Abhilfe wäre:

handleChange(e) {   
    this.setState({ 
     connections : {[e.target.name]: e.target.value, twitter: 'initial val', instagram: 'initial val'} 
    }) 
} 
2

setState führt eine flache merge statt einer tiefen eine (weitere Erklärung in the docs), so dass Sie vollständig alle connections Überschreiben mit nur dein einziger Wert. Wenn Sie die anderen Tasten in connections intakt halten möchten, können Sie handleChange Um dies ändern:

handleChange(e) {   
    this.setState({ 
     connections : {...this.state.connections, [e.target.name]: e.target.value} 
    }) 
} 

Dies wird flache Kopie alle this.state.connections, und legen Sie e.target.name über oben drauf.

+0

Bekam es Drew. Danke für die Antwort. –

Verwandte Themen