Javascript 在React应用程序中更新动态呈现的元素时出现问题

Javascript 在React应用程序中更新动态呈现的元素时出现问题,javascript,html,reactjs,Javascript,Html,Reactjs,我受够了。创建connect 4游戏时,我被困在需要更新所选单元格的部分 基于此代码,它的行为如何 只有从左上到右的对角线单元格显示一个红色圆圈,但它忽略了它的容器div HTML和CSS。它只占了那个div的空间 其他单元格根本不显示红色圆圈 如果我在点击其中一个产生红色圆圈的单元格后点击任意位置,就会出现错误“UncaughtTypeError:无法读取undefined的属性'key'” 如果在单击“非循环生成”单元格后单击任何单元格,控制台日志会将其添加到数组的末尾 错误: undefi

我受够了。创建connect 4游戏时,我被困在需要更新所选单元格的部分

基于此代码,它的行为如何

  • 只有从左上到右的对角线单元格显示一个红色圆圈,但它忽略了它的容器div HTML和CSS。它只占了那个div的空间
  • 其他单元格根本不显示红色圆圈
  • 如果我在点击其中一个产生红色圆圈的单元格后点击任意位置,就会出现错误“UncaughtTypeError:无法读取undefined的属性'key'”
  • 如果在单击“非循环生成”单元格后单击任何单元格,控制台日志会将其添加到数组的末尾
  • 错误:

    undefined: {$$typeof: Symbol(react.element), type: "div", key: "06", ref: null, props: {…}, …}
    
    createBoards=()=>{
    让gameBoard=[]
    for(设i=0;i<6;i++){
    游戏板[i]=[]
    对于(设j=0;j<7;j++){
    游戏板[i]。推(
    这个.playerMove(e)}>
    )
    }
    }
    这是我的国家({
    游戏板:游戏板
    },函数(){
    console.log(this.state.gameBoard)
    })
    }
    
    playerMove=(e)=>{
    让copyUserBoard=[…this.state.gameBoard]
    设id=e.target.id
    设i=e.target.id.split(“”).map(编号)
    let element=copyUserBoard[i[0][i[1]].props.children
    让clonedElement=React.cloneElement(
    元素,
    {className:“red”,key:id}
    )
    for(设i=0;i<6;i++){
    对于(设j=0;j<7;j++){
    if(id==copyUserBoard[i][j].key){
    让newArr=Object.assign([],copyUserBoard,{[[i][j]]:clonedElement})
    这是我的国家({
    游戏板:纽瓦尔
    })
    console.log(this.state.gameBoard)
    }
    }
    }
    }
    
    我建议您独立于DOM维护板的状态。下面是一个你可以如何做的例子。如果您有问题或任何需要澄清的地方,请告诉我

    (我知道这不是connect four的工作原理。关键不是游戏机制,而是反应状态管理。)

    //要渲染多少块板
    const NUM_BOARDS=3;
    //行数和列数
    施工板尺寸=5;
    //已占用单元格的值,
    //也用作css类
    常数PLAYER_1='p1';
    常数PLAYER_2='p2';
    //为方便起见,请交替播放
    常量玩家=[PLAYER_1,PLAYER_2];
    //板上一行的反应组件。
    //props.cells-一组对象,每个对象具有
    //一个值为PLAYER_1的“value”属性,
    //PLAYER_2,或null
    //props.onCellClick-用于
    //告诉董事会某个特定单元格被点击。
    常量行=({cells,onCellClick})=>(
    
      { cells.map(({value},index)=>(
    • onCellClick(索引)} className={'cell${value==null?'empty':PLAYERS[value]}`>
    • )) }
    ) 类板扩展React.Component{ 建造师(道具){ 超级(道具); 此.state={ 玩家:0, 行:数组。from({length:BOARD_SIZE},()=>({ 单元格:数组.from({length:BOARD_SIZE},()=>({value:null})) })) }; } onCellClick=(行、单元格)=>{ const{rows,player}=this.state; 行[行]。单元格[单元格]={value:player}; 这是我的国家({ 行:[……行], 玩家:(玩家+1)%2, }) } 渲染(){ const{rows}=this.state; 返回(
      {rows.map((row,rowIndex)=>(
    • this.onCellClick(rowIndex,cellIndex)}cells={row.cells}/>
    • ))}
    ); } } 类ConnectFour扩展了React.Component{ render(){ 返回( { //发射板 Array.from({length:NUM_BOARDS}).map({uu,i)=>(
  • )) } ) } } ReactDOM.render(,document.querySelector(#app))
    正文{
    填充:20px;
    }
    李先生{
    填充:0;
    保证金:0;
    列表样式:无;
    }
    #应用程序{
    背景:#fff;
    边界半径:4px;
    填充:20px;
    过渡:均为0.2s;
    }
    .董事会{
    --尺寸:40px;
    填充:10px;
    保证金:10px自动;;
    }
    .行{
    显示器:flex;
    证明内容:中心;
    高度:var(--大小);
    }
    .行.单元格{
    弹性:0变量(--大小);
    保证金:1px;
    }
    .row>.empty{
    背景:#ccc;
    }
    .row>.cell.p1{
    背景:红色;
    边界半径:50%
    }
    .row>.cell.p2{
    背景:蓝色;
    边界半径:50%
    }
    
    
    我建议您独立于DOM维护板的状态。我会试着用一个例子来说明我的意思,并在一分钟内发布。@ray hatfield谢谢!期待它;)我没有忘记,但我需要离开一会儿。我回来后会收拾东西的。抱歉耽搁了。谢谢你这么做!昨天我接受了你的建议,开始做一些改变,但这里有一些好东西我需要从快乐帮助中学到。这里的关键思想是DOM是状态的表示,而不是状态本身。
    createBoards = () => {
        let gameBoard = []
    
        for (let i = 0; i < 6; i++) {
          gameBoard[i] = []
          for (let j = 0; j < 7; j++) {
            gameBoard[i].push(
              <div className="box" key={[i]+[j]}>
                <div
                  className="black"
                  id={[i]+[j]}
                  onClick={ (e) => this.playerMove(e)}>
                </div>
              </div>
            )
          }
        }
        this.setState({
          gameBoard: gameBoard
        }, function () {
          console.log(this.state.gameBoard)
        })
      }
    
    playerMove = (e) => {
        let copyUserBoard = [...this.state.gameBoard]
        let id = e.target.id
        let i = e.target.id.split('').map(Number)
        let element = copyUserBoard[i[0]][i[1]].props.children
    
        let clonedElement = React.cloneElement(
          element,
          { className: "red", key: id }
        )
    
        for (let i = 0; i < 6; i++) {
          for (let j = 0; j < 7; j++) {
            if (id === copyUserBoard[i][j].key) {
              let newArr = Object.assign([], copyUserBoard, {[[i][j]]: clonedElement})
    
              this.setState({
                gameBoard: newArr
              })
              console.log(this.state.gameBoard)
            }
          }
        }
    
      }