2017-04-10 85 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