响应中的树重新呈现

时间:2017-09-12 15:02:04

标签: javascript reactjs jsx

我正在运行此代码,每次单击一个对象时,整个元素树都会重新渲染。因为我的handleClick方法在renderCard方法内,所以我点击的元素不应该是唯一一个重新渲染的元素。我认为它与renderCard方法的个性有关,因为每一个都不具体,这就是为什么所有这些都重新渲染,所以我应该作为道具传递我要重新渲染的卡号?不是什么问题?

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

class CardNEW extends React.Component{

    render(){
        return(
            <span className={"card rank-" + this.props.rank+" "+this.props.suit+""}>
                        <span className="rank">{this.props.rank}</span>
                        <span className="suit"></span>
                    </span>
            );
    }
    }


class Game extends React.Component{
    constructor(){
        super();
        this.newdeck=this.deckCreator();
        this.handleClick = this.handleClick.bind(this);
    }
    deckCreator(){
        const deckdiamonds=[];
        const deckspades=[];
        const deckclubs=[];
        const deckhearts=[];
      for(let i=0;i<13;i++){
        if(i==0){
            deckspades.push(['a','spades'])
        }else if(i==10){
            deckspades.push(['j','spades'])
        }else if(i==11){
            deckspades.push(['q','spades'])
        }else if(i==12){
            deckspades.push(['k','spades'])
        }else{
        deckspades.push([i+1,'spades'])
        }
      }
      for(let k=0;k<13;k++){
        if(k==0){
            deckdiamonds.push(['a','diams'])
        }else if(k==10){
            deckdiamonds.push(['j','diams'])
        }else if(k==11){
            deckdiamonds.push(['q','diams'])
        }else if (k==12) {
            deckdiamonds.push(['k','diams'])
        }else{
        deckdiamonds.push([k+1,'diams'])
        }   
      }
      for(let l=0;l<13;l++){
        if(l==0){
            deckclubs.push(['a','clubs'])
        }else if(l==10){
            deckclubs.push(['j','clubs'])
        }else if(l==11){
            deckclubs.push(['q','clubs'])
        }else if (l==12) {
            deckclubs.push(['k','clubs'])
        }else{
        deckclubs.push([l+1,'clubs'])
      }
    }   
      for(let m=0;m<13;m++){
        if(m==0){
            deckhearts.push(['a','hearts'])
        }else if(m==10){
            deckhearts.push(['j','hearts'])
        }else if(m==11){
            deckhearts.push(['q','hearts'])
        }else if (m==12) {
            deckhearts.push(['k','hearts'])
        }else{
        deckhearts.push([m+1,'hearts'])
      }
      }
      return deckdiamonds.concat(deckspades,deckclubs,deckhearts);
    }   
    handleClick(i){
            this.setState({rank:1 ,suit:2})
            console.log('yo' + this.state);
    }

    cardDraw(deck){ 
    let cut=Math.floor((Math.random() * deck.length) + 0);
    let card=deck.splice(cut, 1);
    console.log('ya' + this.state);
    return card;
    }

    renderCard(i){  
        const newcard=this.cardDraw(this.newdeck);
                return(
                <button onClick={this.handleClick}>
                    <span className="playingCards simpleCards">
                        <CardNEW rank={newcard[0][0]} suit={newcard[0][1]}/>                    
                    </span>
                </button>); 
    }

    render() {
    return (
      <span>
        <span className="opponent-hand">
          {this.renderCard(1)}
            {console.log('yei')}
          {this.renderCard(2)}          
          {this.renderCard(3)}
          {this.renderCard(4)}
          {this.renderCard(5)}
        </span>
        <div className="my-hand">
          {this.renderCard(6)}
          {this.renderCard(7)}
          {this.renderCard(8)}
          {this.renderCard(9)}
          {this.renderCard(0)}
        </div>
      </span>
    );
  }
}

ReactDOM.render(<Game />, document.getElementById("root"));

一些额外信息:日志用于识别我的问题,忽略它们。我知道那里可能有一些反模式,但我上周开始使用js所以我正在学习。非常重要我知道handleclick方法没有做任何事情它设置为对象Object,这是一个问题我会稍后解决

1 个答案:

答案 0 :(得分:0)

React的渲染功能就像这样;

  1. 状态通过setState更改。
  2. React对“虚拟dom”上状态已更改的组件执行不可见的测试重新渲染。
  3. 作为步骤2的结果,反应也重新渲染虚拟dom上的所有子组件。这将以递归方式继续,直到找到非组件元素。
  4. 对于在虚拟dom上重新渲染的每个元素,react会将新结果与之前的结果进行比较。
  5. 如果新结果与之前的结果不匹配,则反应会重新呈现子组件。
  6. 考虑到这一点,请考虑您的代码如何输入此流程;在虚拟dom渲染中,您的代码将重新运行cardDraw方法,从而产生随机结果。这意味着它将始终产生一个独特的结果,并且总是被重新渲染。

    如果要阻止这种情况,则需要将cardDraw的第一个结果存储在可以引用先前结果的位置,从而保留子组件的相同渲染。存储此结果的适当位置在州。

    我会在状态上创建一个大小为10的数组,并用10个cardDraw调用填充它。每当您需要检索以前绘制的卡片时,请参考this.state.cards[index]