Javascript React setState在调用时渲染组件两次

Javascript React setState在调用时渲染组件两次,javascript,reactjs,components,Javascript,Reactjs,Components,我正在尝试构建一个connect 4游戏,它有一个由7列组件组成的棋盘组件,所有组件都包含6个空格组件。每列上都有一个下拉按钮,用于将工件放入列中。为了在“红色”和“黑色”播放器之间切换,我创建了一个状态“redOrBlue”,它返回一个布尔值 简而言之,当点击下拉按钮时,我想切换“redOrBlue”的值以跟踪轮到谁了。我已经将onClick函数设置为setState({redOrBlue:!this.state.redOrBlue)},但是,调用此函数将导致react在单击按钮的列的正下方呈

我正在尝试构建一个connect 4游戏,它有一个由7列组件组成的棋盘组件,所有组件都包含6个空格组件。每列上都有一个下拉按钮,用于将工件放入列中。为了在“红色”和“黑色”播放器之间切换,我创建了一个状态“redOrBlue”,它返回一个布尔值

简而言之,当点击下拉按钮时,我想切换“redOrBlue”的值以跟踪轮到谁了。我已经将onClick函数设置为setState({redOrBlue:!this.state.redOrBlue)},但是,调用此函数将导致react在单击按钮的列的正下方呈现一个额外的列。我知道setState会自动重新呈现DOM,但我如何避免它呈现组件的副本呢?谢谢你的帮助

class Column extends Component{
  constructor(){
    super();
    this.state = {
      myArray: [],
      buttonArray: [],
      buttonNumber: null,
      newArray: [],
      redOrBlue: true
    }
  }
  makeRow(){
    var component = <Space className="space"/>
    for(var i = 0; i < 6; i++){
      this.state.myArray.push(component);
    }
  }

  handleClick(){
    var num = this.props.colNumber;
    var array = this.props.boardArray[num];
    var boolean = false;
    var color;
    if(this.state.redOrBlue === true){
      color = "red"
    }else{
      color = "black"
    }
    for(var i = 5; i > -1; i--){
      if(boolean === false){
        if(array[i] === null){
          array[i] = color;
          boolean = true;
        }
      }
    }
    this.setState({redOrBlue: !this.state.redOrBlue})
    console.log(array)
  }

  render(){
    {this.makeRow()}
    return(
      <div className="column">
        <DropButton onClick={() => this.handleClick()} id={'button-' + this.props.colNumber} buttonNumber={this.props.colNumber} className={this.props.className}/>
        {this.state.myArray.map(function(component, key){
          return component
        })}
      </div>
    )
  }
}
类列扩展组件{
构造函数(){
超级();
此.state={
myArray:[],
buttonArray:[],
按钮编号:空,
新阵列:[],
redOrBlue:对
}
}
makeRow(){
变量分量=
对于(变量i=0;i<6;i++){
this.state.myArray.push(组件);
}
}
handleClick(){
var num=this.props.colNumber;
var数组=this.props.boardArray[num];
布尔值=false;
颜色变异;
if(this.state.redOrBlue==true){
color=“红色”
}否则{
color=“黑色”
}
对于(变量i=5;i>-1;i--){
如果(布尔===false){
if(数组[i]==null){
数组[i]=颜色;
布尔=真;
}
}
}
this.setState({redOrBlue:!this.state.redOrBlue})
console.log(数组)
}
render(){
{this.makeRow()}
返回(
this.handleClick()}id={'button-'+this.props.colNumber}buttonNumber={this.props.colNumber}className={this.props.className}/>
{this.state.myArray.map(函数(组件,键){
返回组件
})}
)
}
}
从渲染函数中删除
{this.makeRow()}
。您所做的只是在每次组件渲染时,以一种非犹太方法向状态添加另一行。试着这样做:

  constructor(){
    super();
    this.state = {
      myArray: [],
      buttonArray: [],
      buttonNumber: null,
      newArray: [],
      redOrBlue: true
    }
    this.makeRow();
  }
  makeRow(){
    var tempArray = [];
    var component = <Space className="space"/>
    for(var i = 0; i < 6; i++){
      tempArray.push(component);
    }
    this.setState({ myArray: tempArray }};
  }
makeRow(){
    var component = [];
    for(var i = 0; i < 6; i++){
      component.push(<Space key={i} className="space"/>);
    }
    return component;
 }

render(){
    return(
        <div className="column">
            <DropButton onClick={() => this.handleClick()} id={'button-' + this.props.colNumber}
                buttonNumber={this.props.colNumber} className={this.props.className}/>
            {this.makerow()}
        </div>
    )
}
constructor(){
超级();
此.state={
myArray:[],
buttonArray:[],
按钮编号:空,
新阵列:[],
redOrBlue:对
}
this.makeRow();
}
makeRow(){
var tempArray=[];
变量分量=
对于(变量i=0;i<6;i++){
tempArray.push(组件);
}
this.setState({myArray:tempArray}};
}
从渲染函数中删除
{this.makeRow()}
。每次组件渲染时,您所做的只是以一种非犹太方法向状态中添加另一行。请尝试以下操作:

  constructor(){
    super();
    this.state = {
      myArray: [],
      buttonArray: [],
      buttonNumber: null,
      newArray: [],
      redOrBlue: true
    }
    this.makeRow();
  }
  makeRow(){
    var tempArray = [];
    var component = <Space className="space"/>
    for(var i = 0; i < 6; i++){
      tempArray.push(component);
    }
    this.setState({ myArray: tempArray }};
  }
makeRow(){
    var component = [];
    for(var i = 0; i < 6; i++){
      component.push(<Space key={i} className="space"/>);
    }
    return component;
 }

render(){
    return(
        <div className="column">
            <DropButton onClick={() => this.handleClick()} id={'button-' + this.props.colNumber}
                buttonNumber={this.props.colNumber} className={this.props.className}/>
            {this.makerow()}
        </div>
    )
}
constructor(){
超级();
此.state={
myArray:[],
buttonArray:[],
按钮编号:空,
新阵列:[],
redOrBlue:对
}
this.makeRow();
}
makeRow(){
var tempArray=[];
变量分量=
对于(变量i=0;i<6;i++){
tempArray.push(组件);
}
this.setState({myArray:tempArray}};
}

您需要在代码中更改许多内容:

*首先,从不
ui项
存储在状态变量中,
状态
变量应仅包含数据和值

*切勿通过
this.state.a=''或this.state.a.push({})
状态
变量进行任何更改,始终将
状态
值视为不可变的,并且仅使用
设置状态
更改值

*始终调用
render
中的函数,如果您想动态创建
内容,该函数将直接创建
ui部分

从render调用
makeRow
方法,它将直接返回ui,而不将其存储在状态变量中,如下所示:

  constructor(){
    super();
    this.state = {
      myArray: [],
      buttonArray: [],
      buttonNumber: null,
      newArray: [],
      redOrBlue: true
    }
    this.makeRow();
  }
  makeRow(){
    var tempArray = [];
    var component = <Space className="space"/>
    for(var i = 0; i < 6; i++){
      tempArray.push(component);
    }
    this.setState({ myArray: tempArray }};
  }
makeRow(){
    var component = [];
    for(var i = 0; i < 6; i++){
      component.push(<Space key={i} className="space"/>);
    }
    return component;
 }

render(){
    return(
        <div className="column">
            <DropButton onClick={() => this.handleClick()} id={'button-' + this.props.colNumber}
                buttonNumber={this.props.colNumber} className={this.props.className}/>
            {this.makerow()}
        </div>
    )
}
makeRow(){
var分量=[];
对于(变量i=0;i<6;i++){
component.push();
}
返回组件;
}
render(){
返回(
this.handleClick()}id={'button-'+this.props.colNumber}
buttonNumber={this.props.colNumber}className={this.props.className}/>
{this.makerow()}
)
}

您需要在代码中更改许多内容:

*首先,从不
ui项
存储在状态变量中,
状态
变量应仅包含数据和值

*切勿通过
this.state.a=''或this.state.a.push({})
状态
变量进行任何更改,始终将
状态
值视为不可变的,并且仅使用
设置状态
更改值

*始终调用
render
中的函数,如果您想动态创建
内容,该函数将直接创建
ui部分

从render调用
makeRow
方法,它将直接返回ui,而不将其存储在状态变量中,如下所示:

  constructor(){
    super();
    this.state = {
      myArray: [],
      buttonArray: [],
      buttonNumber: null,
      newArray: [],
      redOrBlue: true
    }
    this.makeRow();
  }
  makeRow(){
    var tempArray = [];
    var component = <Space className="space"/>
    for(var i = 0; i < 6; i++){
      tempArray.push(component);
    }
    this.setState({ myArray: tempArray }};
  }
makeRow(){
    var component = [];
    for(var i = 0; i < 6; i++){
      component.push(<Space key={i} className="space"/>);
    }
    return component;
 }

render(){
    return(
        <div className="column">
            <DropButton onClick={() => this.handleClick()} id={'button-' + this.props.colNumber}
                buttonNumber={this.props.colNumber} className={this.props.className}/>
            {this.makerow()}
        </div>
    )
}
makeRow(){
var分量=[];
对于(变量i=0;i<6;i++){
component.push();
}
返回组件;
}
render(){
返回(
this.handleClick()}id={'button-'+this.props.colNumber}
buttonNumber={this.props.colNumber}className={this.props.className}/>
{this.makerow()}
)
}

好的,那么当页面加载时,我在哪里/如何调用该函数呢?您有几个选项。从构造函数调用该函数可能是最简单的。@IanSpringer,我编辑了我的答案,以显示一种方法,您可以这样做。好的,那么当页面加载时,我在哪里/如何调用该函数呢?您有几个选项。它可以从构造函数调用该函数是最容易的。@IanSpringer,我已经编辑了我的答案,以显示一种方法,您可以这样做。