изменение состояния отдельных компонентов реакции - PullRequest
0 голосов
/ 02 октября 2019

Я новичок в React и начал работать над игрой в память, где вы переворачиваете карты и сравниваете две карты. У меня проблемы с пониманием, как изменить состояние отдельных компонентов. теперь, когда я щелкаю по компоненту, состояние всех компонентов меняется, и все мои карты становятся красными вместо одной. позже я думал добавить фотографии, а пока просто тестировать с цветом фона. Также я знаю, что должен добавить некоторые логику / функции, но не могу решить проблему состояния.

App.js

import React, {Component} from 'react';
import './App.css';
import Grid from './grid/grid';
import Header from './Header/header';
import Footer from './Footer/footer';

class App extends Component {

  cards = [{id:1, name: 'dog'},{id:2, name: 'dog'},{id:3, name: 'cat'},{id:4, name: 'cat'},{id:5, name: 'mouse'},{id:6, name: 'mouse'},{id:7, name: 'horse'},{id:8, name: 'horse'},
    {id:9, name: 'pig'},{id:10, name: 'pig'},{id:11, name: 'chicken'},{id:12, name: 'chicken'},{id:13, name: 'cow'},{id:14, name: 'cow'},{id:15, name: 'fox'},{id:16, name: 'fox'}]
    .sort( () => Math.random() - 0.5);

  clicks = [];

  state = {
    current: 0,
  }

  clickHandler = (click) => {
    this.clicks.push(click.name);
    this.setState({
      current: 1
    })
    console.log(this.clicks);
    if (this.clicks.length > 1) {
      this.compare(click.name);
    }
  }

  compare = (name) => {
    if (name === this.clicks[0]) {
      console.log('pair')
    } else {
      console.log('nope');
    }
  }

  render() {
  return (
    <div className="App">
      <Header />
      <div className='Grid-container'>
        <div className='wrapper'>
        {this.cards.map(child =>
        <Grid click={() => this.clickHandler(child)} 
              active={this.state.current === 0}
              id={child.id}
              />)}
        </div>
      </div>
      <Footer />
    </div>
  );
  }
}

export default App;

сетка. js

import React from 'react';
import './grid.css';

const Grid = (props) => {
        return (
            <div className={'Child' + (props.active ? '': ' active')} 
            onClick={props.click}
            >
                {props.id}
            </div>
        );
    }


export default Grid;

App.css

.Grid-container {
  display: flex;
  background-color: black;
  justify-content: center;
  align-items: center;
}
.wrapper {
  display: grid;
  width: 700px;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(4, 1fr);
  grid-gap: 10px;
  background-color: black;
  justify-content: center;
  align-items: center;
}

**grid.css**

.Child {
    width: auto;
    height: 120px;
    background-color: azure;
    border-radius: 10px;
}
.Child.active {
    width: auto;
    height: 120px;
    background-color: red;
    border-radius: 10px;
}

Ответы [ 2 ]

0 голосов
/ 02 октября 2019

Обновление состояния раздела

  state = {
    current: -1, // nothing is selected it contains id of selected card
    clicks: [],
  }
  clickHandler = (selectedId) => {
    const { clicks, current } = this.state;
    if (current === -1) { // no card selected to check
      this.setState({
         current: selectedId,
         clicks: clicks.includes(selectedId) ? clicks : [...clicks, selectedId],
      });
      return; // no more in this funtion
    }
    if (selectedId === current) { // already selected card(totally same card)
      this.setState({
        current: -1,  // unselect last selected card :(
        clicks: clicks.slice(0, clicks.length - 1), // remove last selected click
      });
    } else { // different card. here check if they have same name
      if (this.cards[selectedId].name === this.cards[current].name) {
        // couple cards
        console.log('Bingo They are Same!!!');
        this.setState({
          current: -1,
          clicks: [...cliks, selectedId], // add just selected card in cliks
        });
      } else {
        // Oh, you failed!
        this.setState({
          current: -1,  // unselect last selected card :(
          clicks: clicks.slice(0, clicks.length - 1),
        });
      }
    }
  }

Визуализация

...
<Grid
 click={() => this.clickHandler(child.id)} 
 active={this.state.clicks.includes(child.id)} // check if it is included in clicks
 id={child.id}
/>
...

Тогда вы сможете увидеть классную карточную игру. :)

0 голосов
/ 02 октября 2019

Вы должны использовать index для этого. У вас есть index в качестве второго аргумента в map,

{this.cards.map( ( child, index ) =>
    <Grid 
        click={() => this.clickHandler(child,index)} 
        active={this.state.current === index}
        id={child.id}
        key ={child.id} //Provide unique key here
    />
)}

Ваш клик должен быть,

clickHandler = (click,index) => {
    this.clicks.push(click.name);
    this.setState({
      current: index   //Set index in a state
    })
    console.log(this.clicks);
    if (this.clicks.length > 1) {
        this.compare(click.name);
    }
}

Вам нужно инициализировать current состояние как пусто, в противном случае вы получите первую сетку по умолчанию активной

state = {
    current: '',
}

Это будет ваш Grid компонент,

const Grid = (props) => {
    return (
        <div 
            className={`Child ${props.active ? 'active': ''}`}  //Your condition should be this
            onClick={props.click}
        >
            {props.id}
        </div>
    );
}

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...