2017-04-10 52 views
0

有一個陣列看起來如下:Javascript - array.map匹配索引

[[3,0],[6,0],[2,0],[9,0] ....]

我試圖創建一個React/Redux reducer,將其中一個0的值更改爲1.我點擊一個元素並分派一個操作。 IDX是一個元件的陣列中的索引(例如,0,1,2,3)

export const toggleTile = (idx) => { 
    return { 
    type: TOGGLE_TILE, 
    idx 
    }; 
}; 

減速器下面不工作,因爲我想的那樣。我剛剛創建了條件語句的框架。如果我點擊索引爲3的圖塊(所以第四個圖塊),它會將所有元素的[n,0]更改爲[n,1]。首先,它應該只會點擊任何一個圖塊,並且它應該將[n,0]更改爲[n,1]僅用於點擊的圖塊,因此我試圖將下面的代碼中的3更改爲被映射的'i'元素的索引。

export default (state = [], action = {}) => { 
    switch (action.type) { 
    case LOAD_GRID: 
     return action.payload || []; 
    case TOGGLE_TILE: 
     return state.map((i) => { 
     if (action.idx === 3) { 
      return (i[1] === 0 
      ? [i[0], parseInt(i[1], 10) + 1] 
      : [i[0], parseInt(i[1], 10) - 1] 
     ); 
     } 
     return [i[0], i[1]]; 
     }); 
    default: 
     return state; 
    } 
}; 

網格組件:

export default class Grid extends Component { 
    render() { 
    const mygrid = []; 
    this.props.inGrid.forEach((r, i) => { 
     mygrid.push(
     <Square 
      key={i} 
      idx={i} 
      sqValue={r} 
      toggleTile={this.props.toggleTile} 
     /> 
    ); 
    }); 
    const { grid } = styles; 
    return (
     <View style={grid}> 
     {mygrid} 
     </View> 
    ); 
    } 

} 



export default class Square extends Component { 

    myaction() { 
    this.props.toggleTile(this.props.idx); 
    console.log(this.props.idx); 
    } 

    render() { 
    const { square, textStyle, squareActive } = styles; 
    const { sqValue } = this.props; 
    return (
     <TouchableHighlight 
     style={[square, sqValue[1] && squareActive]} 
     onPress={this.myaction.bind(this)} 
     > 
     <View> 
      <Text style={textStyle}>{sqValue[0]},{sqValue[1]}</Text> 
     </View> 
     </TouchableHighlight> 
    ); 
    } 
} 

請指教。

+0

這是「[[3,0],[6,0],[2,0],[9,0] ... ](「我)=」{ – SoEzPz

+0

是的,這是返回的狀態。 – Wasteland

回答

2

有許多的方法可以做到這一點,有不同程度的冗長的(由於終極版對永恆的堅持),但這裏有一個非常簡單的一個:

case TOGGLE_TILE: 
    const nextValue = state[action.idx].slice(); // Make a copy of the tuple to be toggled 
    nextValue[1] = nextValue[1] === 0 ? 1 : 0; // Toggle it 

    const nextState = state.slice();    // Make a copy of the state 
    nextState[action.idx] = nextValue;   // Replace the old tuple with the toggled copy 
    return nextState; 

或者:

case TOGGLE_TILE: 
    const prevValue = state[action.idx]; 
    const nextState = state.slice(); 
    nextState[action.idx] = [ prevValue[0], prevValue[1] === 0 ? 1 : 0 ]; 
    return nextState; 
+0

謝謝 - 簡單 - 我以爲你總是映射返回一個新的狀態數組。 – Wasteland

+1

'map'往往是最方便的,因爲它總是返回一個新的數組(因此確保你不會改變原始數組),但是如果你只更改一個項目,國際海事組織。如果你不使用'map',你需要使用'slice()'來創建一個副本,就像上面的第5行一樣(當然要小心不要改變任何子對象,只要在附加的slice() 2行)。 –

+0

我已經用我的第一個解決方案和您的解決方案之間的第二個解決方案更新了我的答案。沒有比這更好或更糟的了。 –

1

好吧,我會試着看看我們可以用你分享的代碼的下面部分做些什麼。

我想指出所提供的代碼並不簡潔。如果你的代碼被重構了,那麼對你自己,你的團隊以及這個網站上的任何人都會有很大的好處,你越瞭解你需要構建什麼。

// So state is just an array of arrays... 

var state = [3,0], [6,0], [2,0], [9,0]]; 

return state.map((i) => { // i => [3,0] or [9,0] !! i is not index !! 
// Map is going to iterate over the entire array of arrays. 

    if (action.idx === 3) { 
    // action.idx is what comes in from the click. 

    // Here is where your doing your work. 
    // If the first element of "i" is zero, then 
    // return the same array but add 1 to the second element of array. 
    // so [3,0] or [4,0] should become [3,1] or [4,1] but only for #3 as 
    // action.idx === 3 says to only change when... Nope, this is not how it will work. You need your exception in the MAP. 
    return (i[1] === 0 ? [i[0], parseInt(i[1], 10) + 1] : [i[0], parseInt(i[1], 10) - 1]); 
    } 

    // ?? Why don't you just return i, as i is each array of numbers. 
    return [i[0], i[1]]; 
    }); 

// It seams to me that something like this should work, just plug and play. 
// I am assuming a few things here that I will spell out. If they are incorrect, let me know and I'll change it. 

// state will be an array of arrays that only contain two numbers each. 
// They may or may not be in original order. 
// The second element of each array will be either 0 or 1. 

var state = [3,0], [6,0], [2,0], [9,0]]; 

state.map(function(cell){ // call it what you want, you called it "i". 
    if(cell[0] === action.idx){ // If clicked action index is === to cell[0] 
    // You could just hard code 3 as you did above, but this makes it dynamic. 
    // and only changes the cell that was clicked. 
    cell[1] = cell[1] ? 1 : 0; // if cell[1] is 0, then it is falsey, no need for complex logic. No need to parseInt if they are numbers to begin with. But if you do, then use "+" to change a string to number. 
    } 
    return cell; 
}); 

脫稿

var state = [3,0], [6,0], [2,0], [9,0]]; 

state.map(function(cell){ 
    if(cell[0] === action.idx){ 
    cell[1] = cell[1] ? 1 : 0; 
    } 
    return cell; 
}); 
+0

謝謝您的意見 - 採取了船上。 – Wasteland

+0

您的解決方案會改變原始(子)數組,這在Redux中是嚴格禁止的。 –

+0

您的權利違反了redux行爲。我一直在尋找成員問題的答案,這是關於地圖行爲的。 – SoEzPz