Простая интерактивная карта React Tile

Я изо всех сил пытаюсь достичь самой простой вещи. У меня есть эта карта тайлов: скриншот

При нажатии на плитку я могу получить индекс, и оттуда планировалось заменить значение цвета и позволить State изменить фон плитки. Проблема, как представляется, заключается в том, что все плитки с одинаковым цветом меняются на черные, а не только те, которые были нажаты.

скриншот после нажатия на плитку Land/Wheat

Два компонента:

// Map.js 

var mapData = [
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0,0,1,1,1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0,1,1,1,  
]

var tileTypes = {
0: { name: 'Sea', color: 'lightBlue' },
1: { name: 'Land', color: 'wheat' },
2: { name: 'Ship', color: 'black' }
}

var temporalTiles=[];


export default class extends React.Component {


constructor(props) {

super(props)

this.state = {
tile: 0,
tiles:[]
  }
}


componentDidMount() {


const numTiles = mapData.length;

for (let y = 0; y < numTiles; y++) {
    const tileId = mapData[y]
    const tileType = tileTypes[tileId]
    temporalTiles.push(tileType);
    this.setState({tiles: temporalTiles})
  }

}



makeBlack() {
var idx= this.state.tile;

console.log(idx);  // tile index 
console.log(temporalTiles[idx].color); // current tile color 

temporalTiles[idx].color = 'black'; // change color

console.log(temporalTiles[idx].color); // did it work ? yes(!)

this.setState({tiles: temporalTiles})

console.log(temporalTiles);
}


handleIndexToState(idx) {

this.setState({tile: idx})

}

render () {

var quickDemo ={
  display:'block',
  textAlign:'center'
}

return ( <div>

  {this.state.tile ? (

    <div>          
      <p style={quickDemo}> Index of clicked cell {this.state.tile}</p>
      <p style={quickDemo}
        onClick={this.makeBlack.bind(this)}>
        Change to black 
      </p>
    </div>
    ) : null
  }

      {this.state.tiles.map((tile,index) =>(

        <Tile
          bgcolor={tile.color}
          key={index}
          position={index}
          onClick={this.handleIndexToState.bind(this, index)}
        />

        ))}

   </div>)
  }}

Это родительский компонент, компонент Tile выглядит так

 // Tile.js 


 export default class extends React.Component {

 render () {

  var bgColor = {
  backgroundColor: this.props.bgcolor ,
  width: '83px',
  height:'83px',
  border:'1px solid rgba(0,0,0,.1)'

  };

  return (

  <div
  onClick={this.props.onClick}
  style={bgColor}>

  {this.props.position}

  </div>


    )
  }
  }

Какие-нибудь указатели на то, что мне не хватает? Я открыт для других стратегий для карты плиток 'mgmt' в реакции, так как я уверен, что мой подход к этой проблеме очень наивен. ТИА

ОБНОВЛЕНИЕ: конечная цель - сохранить цвет каждой плитки в состоянии, чтобы я мог с ней что-то делать, например сохранять позиции в локальном хранилище, например.

1 ответ

Решение

Вам не нужно использовать states изменить цвет. использование event.target чтобы получить выбранный пункт и изменить css напрямую.

Надеюсь это поможет!

var mapData = [
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0,1,1,1,
1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,0,1,1,1,
1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0,0,1,1,1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0,1,1,1,  
]

var tileTypes = {
0: { name: 'Sea', color: 'lightBlue' },
1: { name: 'Land', color: 'wheat' },
2: { name: 'Ship', color: 'black' }
}

class Tiles extends React.Component{
  constructor(props){
    super(props)
    this.onClick = this.onClick.bind(this)
    this.state = {
      clickedIndex: []
    }
  }
  
  onClick(i){
    const index = this.state.clickedIndex.slice()
    if(index.indexOf(i) === -1){ //handle duplicates
      index.push(i)
      this.setState({clickedIndex: index})
     } 
  } 
  
  render() {
    console.log('clicked Index:', this.state.clickedIndex)
    const nodes = mapData.map((el, i) => {
      const bg = this.state.clickedIndex.indexOf(i) > -1 ? 'black' : tileTypes[el].color
      return <div className="box" onClick={() => this.onClick(i)} style={{background: bg}}>{i}</div>
    })
    return <div>{nodes}</div>
  }
}

ReactDOM.render(<Tiles/>, document.getElementById('app'))
.box{
  height: 40px;
  width: 40px;
  border: 1px solid grey;
  float: left;
  transition: all 0.2s ease;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Другие вопросы по тегам