繁体   English   中英

更改单个反应组件的 state

[英]changing state of individual react component

我是 React 新手,开始开发 memory 游戏,您可以在其中翻转卡片并比较两张卡片。 我无法理解如何更改单个组件的 state。 现在,当我单击一个组件时,所有组件的 state 都会发生变化,并且我的所有卡片都变成红色而不是一张。 后来我想添加照片,但现在只是用背景颜色进行测试。 另外我知道我必须添加一些逻辑/功能,但无法解决 state 问题。

应用程序.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;

应用程序.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;
}

您必须为此使用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 初始化为,否则默认情况下您将获得第一个网格活动

state = {
    current: '',
}

您的Grid组件将是这个,

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

演示

更新 state 部分

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

然后你可以看到很酷的纸牌游戏。 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM