2017-06-28 31 views
0

我保存在國家項目的集合:如何在React中有條件地更新集合中項目的屬性?

this.state = { 
    items: [ 
     { name: "foo", description: "a foo", index: 0 }, 
     { name: "bar", description: "a bar", index: 1 }, 
     { name: "herp", description: "a herp", index: 2 }, 
     { name: "derp", description: "a derp", index: 3 } 
    ] 
}; 

index屬性表示每個項目的集合中的順序位置。在某些時候,我需要重新訂購這些物品。例如,「DERP」可能需要移動到前面,所以其他項目的索引需要更新:

{ name: "derp", description: "a derp", index: 0 }, 
{ name: "bar", description: "a bar", index: 1 }, 
{ name: "herp", description: "a herp", index: 2 }, 
{ name: "foo", description: "a foo", index: 3 } 

我目前使用的更新從updateimmutability-helper包的狀態。不過,我確信這不是正確的方法(雖然它的工作原理):

// originalIndex is a variable holding the original index 
// newIndex is a variable holding the new index 

// initialise updatedItems so we can update within the loop 
let updatedItems = update(this.state.items, { [originalIndex]: {'index': {$set: newIndex}}}); 

for (var i = newIndex; i < this.state.items.length; i++) { 
    if (i !== originalIndex) { 
     updatedItems = update(updatedItems, { [i]: {'index': {set$: parseInt(this.state.items[i].index) + 1}}}); 
    } 
} 

這感覺就像一個巨大的黑客攻擊。

我的問題是,是否有可能用條件邏輯調用更新,所以這個循環可以用一次調用來更新嗎?

+1

似乎有點哈克的'index'是每個對象內部的屬性,如果一切真的是指to是items數組中的索引。 –

+0

同樣@TomFenech說。當元素可以被數組中的索引引用時,不需要索引屬性_within_ an – Pineda

+0

這實際上是一個好點!我沒有想到這一點。 –

回答

2

假設我們拉index財產從每個項目中,您可以創建像這樣的新列表:

const items = this.state.items.slice(); 
const value = items[oldIndex]; 
items.splice(oldIndex, 1);   // remove the one you want to move 
items.splice(newIndex, 0, value); // add it back to the desired index 

this.setState({ items }); 

也就是說,製作列表的(淺)副本,然後使用拼接交換周圍的元素。

由於您一次只能移動一個元件,則使用可以節省線路:

const [value] = items.splice(oldIndex, 1); 

此分配由splice返回到value數組的第一個元素。

如果你想保持index(爲什麼?),那麼你需要重新分配指標:

this.setState({ items: items.map((item, index) => ({ ...item, index })) }); 
+0

謝謝湯姆。我同意事後的看法,包括對象中的索引是毫無意義的。明天我會拍這張照片。 –

1

爲什麼不排序的前手的項目,在渲染():

render(){ 
    let toDisplay = this.state.items.sort((a,b) => { 
     if (a.index <= b.index) { 
      return -1; 
     } 
     if (a.index > b.index) { 
      return 1; 
     } 
     return 0; 
    }); 

    return(
     <div className='foo'> 
      { 
       toDisplay.map((item, i) => { 
        return(
         <div className="bar" key={i}>{ item.name }</div> 
        ); 
       }) 
      } 
     </div> 
    ); 
} 

那麼你只能通過更新state.items:

this.setState({ 
    items: yourUpdatedItems 
}); 
+2

因爲JavaScript的'sort'修改了它的接收器,所以這段代碼會改變'this.state',這是React文檔強烈要求的。你可能想要'let toDisplay = this.state.items.slice()。sort(...)'來操作數組的副本。 –

相關問題