2017-05-06 35 views
4

通過這個code,我可以成功地在一個簡單的物體上使用setState - 當我點擊「Joey」時,名稱變爲「Igor」。如何在嵌套在React JS數組中的對象使用`setState`?

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

但是與此code,其具有嵌套在一個陣列中的多個對象,setState或者不能夠將每個名稱改變爲「伊戈爾」或它必須以某種方式被修改。

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

即使我知道這是setState工作並不怎麼樣,我試圖通過傳遞index然後寫this.state.names[index].name: newname訪問name。這裏沒有驚喜,它沒有​​奏效。

我已經研究過,無法在SO上找到類似的問題,儘管我發現了很多關於不變性幫助者的提及。但我仍然不確定這是否是一條路。

使用setState修改嵌套在數組中的對象的最佳方法是什麼?

+0

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

+0

你怎麼知道哪一個被點擊?你需要一些標識符,比如特定「卡片」的索引。 – Li357

回答

1

已修改了代碼和工作的例子可以發現here

的變化可以在這裏找到:

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

的想法是,你需要通過.bind到索引傳遞到回調函數,與修改後的名稱返回一個新的state陣列。您需要傳遞索引,以便組件知道哪個對象將name更改爲newname

+1

這非常有幫助,謝謝Tay。這有效,但對於其他人可能會看到這一點 - **我沒有提到我原來的問題**,我希望避免使用'.bind(this)'因爲[here](https:// daveceddia。 com/avoid-bind-when-passing-props /)(見方法#2)。在Tay的幫助下,我能夠重寫我的[代碼](https://codesandbox.io/s/rk5mMP5L4) .bind(這個)'。 –

1

我會用這個切換方法:

toggle = (nameYouWantChanged, nameYouWantItChangedTo) => { 

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

} 
+0

謝謝布拉德,這很聰明。你在第7行有一個''''',應該在':obj'之後出現,但這是一個很好的解決方案。我修改了我的[代碼](https://codesandbox.io/s/YzRwAgy0),以便其他人可以看到如何解決這個問題。 –

+0

布拉德,也只是想讓你知道我選擇了Tay的解決方案,因爲他使用'index'使問題不再出現,例如,在數組中的多個對象可能共享相同名稱的情況下。 –

相關問題