各个反应成分的变化状态

时间:2019-10-02 11:32:19

标签: javascript reactjs state

我是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;

grid.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 :(得分:0)

您必须为此使用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>
    );
}

Demo

答案 1 :(得分:0)

更新状态部分

  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}
/>
...

这时您可以看到很酷的纸牌游戏。 :)