2017-05-06 1 views
4

Mit diesem code kann ich erfolgreich setState auf ein einfaches Objekt verwenden - wenn ich auf "Joey" klicke, ändert sich der Name in "Igor".Wie kann ich `setState` mit Objekten verwenden, die in einem Array in React JS verschachtelt sind?

class Card extends React.Component { 
     myFunc =() => {this.props.change('Igor')}; 
     render() { 
      return (
       <p onClick={this.myFunc}>{this.props.name}</p> 
      ) 
     } 
    } 

    class Parent extends React.Component { 
     constructor(props) { 
      super(props) 
      this.state = { name: "Joey" } 
     } 

     toggle = (newname) => { 
      this.setState((prevState, props) => ({ 
       name: newname 
      })); 
     } 

     render() { 
      return (
       <Card change={this.toggle} name={this.state.name} /> 
      ); 
     } 
    } 

Aber mit dieser code, die in einem Array verschachtelt mehrere Objekte hat, setState ist entweder nicht in der Lage, jeden Namen zu „Igor“ zu ändern oder es muss in irgendeiner Weise verändert werden.

class Card extends React.Component { 

     myFunc =() => {this.props.change('Igor')}; 
     render() { 
      return (
       <p onClick={this.myFunc}>{this.props.name}</p> 
      ) 
     } 
    } 

    class Parent extends React.Component { 
     constructor(props) { 
      super(props) 
      this.state = { 
       names: [ 
        { 
         name: "Joey" 
        }, 
        { 
         name: "Sally" 
        }, 
        { 
         name: "Billy" 
        }, 
       ] 
      } 
     } 

     toggle = (newname) => { 
      this.setState((prevState, props) => ({ 
      // what can I put here to change the name I click on to "Igor" 
      })); 
     } 

     render() { 
      const names = this.state.names.map((name, index) => (
       <Card key={index} change={this.toggle} {...name} /> 
      )) 

      return (
       <div> 
        {names} 
       </div> 
      ); 
     } 
    } 

Auch wenn ich weiß, dass dies nicht der Fall ist, wie setState funktioniert, habe ich versucht name zuzugreifen, indem index vorbei und dann this.state.names[index].name: newname zu schreiben. Keine Überraschungen hier, es hat nicht funktioniert.

Ich habe recherchiert und kann ähnliche Fragen zu SO dazu nicht finden, obwohl ich viele Erwähnungen in Bezug auf immutability Helfer gefunden habe. Aber ich bin mir immer noch nicht sicher, ob das der richtige Weg ist.

Was ist der beste Weg, setState zu verwenden, um in einem Array verschachtelte Objekte zu ändern?

+0

'this.setState (this.state)'? –

+0

Woher weißt du, auf welchen geklickt wurde? Sie benötigen eine Kennung, z. B. den Index der spezifischen "Karte". – Li357

Antwort

1

geändert Haben Sie Ihren Code und die Arbeitsweise kann here finden.

Die Veränderungen sind hier zu finden:

toggle = (index, newname) => { 
    this.setState((prevState, props) => ({ 
     // Return new array, do not mutate previous state. 
     names: [ 
      ...prevState.names.slice(0, index), 
      { name: newname }, 
      ...prevState.names.slice(index + 1), 
     ], 
    })); 
} 

render() { 
    const names = this.state.names.map((name, index) => (
     // Need to bind the index so callback knows which item needs to be changed. 
     <Card key={index} change={this.toggle.bind(this, index)} {...name} /> 
    )) 

    return (
     <div> 
      {names} 
     </div> 
    ); 
} 

Die Idee ist, dass Sie den Index in die Callback-Funktion über .bind, und gibt eine neue state Array mit dem geänderten Namen übergeben müssen. Sie müssen den Index übergeben, damit die Komponente weiß, welches Objekt name zu newname geändert werden soll.

+1

Das ist sehr hilfreich, danke Tay. Dies funktioniert aber für andere, die dies später sehen können - ** Ich habe es versäumt, in meiner ursprünglichen Frage ** zu erwähnen, dass ich vermeiden wollte, '.bind (this)' aus dem angegebenen Grund [hier] zu verwenden (https: // daveceddia. com/avoid-bind-when-passing-props /) (siehe "Weg # 2). Mit Tay's Hilfe konnte ich meinen [code] (https://codesandbox.io/s/rk5mMP5L4) umschreiben, ohne '' zu verwenden .bind (das) '. –

1

Ich würde dies für die Toggle-Methode verwenden:

toggle = (nameYouWantChanged, nameYouWantItChangedTo) => { 

    this.setState({ 
    names: this.state.names.map(obj => 
     obj.name === nameYouWantChanged 
     ? { name: nameYouWantItChangedTo } 
     : obj 
    ) 
    }) 

} 
+0

Danke Brad, das ist ziemlich schlau. Sie haben eine fehlende ')' in Zeile 7, die hinter ': obj' stehen sollte, aber das ist eine großartige Lösung. Ich habe meinen [code] (https://codesandbox.io/s/YzRwAgy0) geändert, damit andere sehen können, wie dies das Problem löst. –

+0

Brad wollte auch nur, dass Sie wissen, dass ich Tay's Lösung über Ihre gewählt habe, da seine Verwendung von 'index' Probleme verhindert, zB wenn mehrere Objekte im Array denselben Namen haben. –

Verwandte Themen