Простая интерактивная карта 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>