我正在使用NextJS/Reaction开发一个简单的测试应用程序,最后我有一个问题.

代码如下:

Board.tsx文件内容:

'use client'

import './Board.css';
import {useState} from 'react';


export default function Board({count}:{count:number}) {
  const [cellLights,setCellLights] = useState(Array.from({length:0},()=>
                                              Array.from({length:0},()=>false)));
  const refresh = () => {
    let tempLights:boolean[][] = cellLights;
    for (let idx=0; idx<tempLights.length; idx++) {
      for (let idix=0; idix<tempLights[idx].length; idix++) {
        tempLights[idx][idix] = false;
      }
    }
    setCellLights(tempLights)
  } /* End of refresh */


  let rows:number[] = [];
  while (rows.length<count) {rows.push(rows.length)}

  let tempLights:boolean[][] = [];
  rows.forEach(rowElt => {
    let rowLights:boolean[] = [];
    rows.forEach(colElt => {
      rowLights.push(false)
    });
    tempLights.push(rowLights)
  });

  if (tempLights.length!=cellLights.length) setCellLights(tempLights)

  return <div className="board">
    {
      rows.map(item => (
        <div key={item}>
          <Row count={count}
               flags={cellLights[item]}
               cleanFn={refresh}/>
        </div>
      ))
    }
  </div>
} /* End of Board */


function Row({count,flags,cleanFn}:{count:number,flags:boolean[],cleanFn:()=>void}) {
  let cells:number[] = [];
  while (cells.length<count) {cells.push(cells.length)}
    return <div className="row">
  {
    cells.map(item => (
      <div key={item}>
        <Cell flag={flags[item]}
              cleanFn={cleanFn}/>
      </div>
    ))
  }
</div>
} /* End of Row */


function Cell({flag,cleanFn}:{flag:boolean,cleanFn:()=>void}) {
    const [high, setHighFlag] = useState(flag);

  function cellClick() {
    cleanFn();
    setHighFlag(!high)
  }

return <>
    {(!high) && <div className="cell" onClick={cellClick}/>}
    {(high) && <div className="cell high" onClick={cellClick}/>}
  </>
} /* End of Cell */

和Board.css文件内容:

.cell {
  width: 3rem;
  height: 3rem;
  background-color: rgb(255, 255, 0);
  border-width: 2px;
  border-color: rgb(55, 55, 55);
  margin:0.1rem;
}

.high {
  background-color: rgb(255, 0, 0);
}

.row {
  display: flex;
  flex-direction: row;
}

.board {
  display: flex;
  flex-direction: column;
}

顶部是app/page.tsx文件:

import Image from 'next/image'
import Board from './components/Board'

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
    {/* // <main> */}
      X4C APP
      <Board count={3}/>
    </main>
  )
}

以下是运行该应用程序时,在单击两个正方形单元格后出现在网络浏览器中的内容:

enter image description here

现在我的问题来了.用户可以看到两个以红色突出显示的单元格.但这并不是我从我的代码中期望的.

由于当执行单击时,会调用cleanFn(),从而调用refresh(),因此我预计在最后单击的单元格变为红色之前,先前突出显示的单元格将恢复为其原始 colored颜色 (黄色).

看到截图,显然不是这样的.有人能看到代码中的缺陷在哪里吗?

推荐答案

cellLights数组数据重复太多.实际上,代码是重新计算数组数据,并将额外的数据作为props向下传递.问题是细胞组件在冲浪板组件的cellLights状态更新时不会重置其状态.

更新代码,使cellLights成为单元格突出显示的唯一真理来源.

冲浪板

function 冲浪板({ count }: { count: number }) {
  // Initialize to count x count board
  const [cellLights, set细胞Lights] = useState(
    Array.from({ length: count }, () =>
      Array.from({ length: count }, () => false)
    )
  );

  const toggle细胞 = (row: number, col: number) => {
    // Reset board, toggle specific cell true
    set细胞Lights(
      Array.from({ length: count }, (_, r) =>
        Array.from({ length: count }, (_, c) => row === r && col === c)
      )
    );
  };

  return (
    <div className="board">
      {cellLights.map((flags, row) => (
        <div key={row}>
          <划 row={row} flags={flags} toggle细胞={toggle细胞} />
        </div>
      ))}
    </div>
  );
}

function 划({
  flags,
  toggle细胞,
  row
}: {
  row: number;
  flags: boolean[];
  toggle细胞: (row: number, col: number) => void;
}) {
  return (
    <div className="row">
      {flags.map((flag, col) => (
        <div key={col}>
          <细胞 flag={flag} toggle细胞={toggle细胞.bind(null, row, col)} />
        </div>
      ))}
    </div>
  );
}

细胞

function 细胞({ flag, toggle细胞 }: { flag: boolean; toggle细胞: () => void }) {
  return <div className={flag ? "cell high" : "cell"} onClick={toggle细胞} />;
}

Demo

Edit display-update-issue-in-a-nextjs-react-app

enter image description here enter image description here enter image description here

Css相关问答推荐

在COLOR-MIX()中使用var()似乎会使其对于不支持COLOR-MIX()的浏览器具有可读性,从而阻止了回退的工作

悬停时可展开的按钮与屏幕右侧对齐,如何保持未悬停的按钮正确对齐?

输入中的框始终显示在MUI文本字段中

Next.js中的TailWind CSS类名称疑难解答

使用 React JS 和自定义 CSS 创建 Cookie 横幅

为什么每次加载新页面时我的 React 侧边栏都会抖动?

和号 (&) 作为 SASS @mixin 中的变量

antd 中的子菜单项不可滚动

如何断言 CSS 属性包含Cypress 测试中的一些文本?

包装器内两个跨度之一上的文本溢出省略号

使用 Bootstrap 设置身体的最大宽度

css 单行或多行垂直对齐

使用 float:left 后如何获得新行?

CSSzoom 高度以匹配宽度 - 可能与外形尺寸

bootstrap 程序中有 7 个相等的列

如何在 CSS 中绘制一个圆形扇区?

完成后如何防止css3动画重置?

从样式设置为 % 的元素获取宽度(以像素为单位)?

background-position-x (background-position-y) 是标准的 W3C CSS 属性吗?

仅当将 Div 悬停在上方时才显示滚动条?