Javascript - array.map匹配索引

时间:2017-04-10 21:28:22

标签: javascript arrays redux

有一个数组如下:

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

请告知。

2 个答案:

答案 0 :(得分:2)

有很多方法可以做到这一点,不同程度的冗长(由于Redux坚持不变性),但这是一个非常简单的方法:

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;

答案 1 :(得分: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;
});