【问题标题】:Trouble with React not updating state (hooks)React 不更新状态的问题(钩子)
【发布时间】:2020-12-30 22:12:12
【问题描述】:

我正在构建一个小型记忆游戏来学习 React。这个想法是你点击一个瓷砖,它被洗牌,你试着选择一个你还没有选择的。问题是我似乎无法获取之前已看到要更新的图块的内部状态。

这是我的组件:

const Gameboard = (props) => {
  const [tiles, setTiles] = useState([]);
  const [currentScore, setCurrentScore] = useState(0);
  const [highScore, setHighScore] = useState(0);
  const [previouslySeen, setPreviouslySeen] = useState([]);

  const handleClick = (evt) => {
    const tile = evt.target;
    if (!previouslySeen.includes(tile)) {
      setCurrentScore(current => current + 1);
      props.setCurrentScore(current => current + 1);
      setPreviouslySeen([...previouslySeen, tile]);
    } else {
      alert("Game over, thanks for playing!");
      if (currentScore > highScore) {
        setHighScore(currentScore);
        props.setHighScore(currentScore);
      }
      setCurrentScore(0);
      props.setCurrentScore(0);
      setPreviouslySeen([]);
    }
  };

  const generateTiles = (tileCount) => {
    return [...Array(tileCount).keys()].map((n) => {
      return <Tile key={n} number={n} handleClick={handleClick} />;
    });
  };

  const shuffleTiles = (tiles) => {
    let tilesCopy = [...tiles];

    for (let i = tilesCopy.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * i);
      const temp = tilesCopy[i];
      tilesCopy[i] = tilesCopy[j];
      tilesCopy[j] = temp;
    }

    return tilesCopy;
  };

  useEffect(() => {
    const initialTiles = generateTiles(props.tileCount);
    setTiles(shuffleTiles(initialTiles));
  }, []);

  useEffect(() => {
    setTiles((oldTiles) => {
      const newTiles = shuffleTiles(oldTiles);
      return newTiles;
    });
  }, [currentScore, highScore]);

  return <div className="Gameboard">{tiles}</div>;
};

handleClick 方法被传递到单独的Tile 组件中,并被onClick 调用。 handleClick method is what is giving me trouble, it seems as if it doesn't ever update previouslySeen`,我在父组件中设置高分以使其反映在 UI 中时遇到类似的问题。你应该如何在 React 中处理这样的更新?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    试试这个:

    const handleClick = (evt) => {
    const tile = evt.target;
    if (!previouslySeen.includes(tile)) {
      setCurrentScore(current => current + 1);
      props.setCurrentScore(current => current + 1);
      // Change the following line:
      setPreviouslySeen(previousState => [...previousState, tile]);
    } else {
    

    此外,您从父道具从声明状态中获得setCurrentScore, setHighScore

      const [currentScore, setCurrentScore] = useState(0);
      const [highScore, setHighScore] = useState(0);
    

    所以本质上你保留了两个独立的currentScorehighScore 状态——一个在Gameboard 组件中,一个在它的父组件中。最好从Gameboard中删除这些状态变量和setter,直接从parent props中获取。

    【讨论】:

    • 我绝对是通过两次存储状态来做一些愚蠢的事情(这是由于尝试尝试解决上述问题),但最终由于某种原因直接将 JSX 存储在状态中导致了问题.
    【解决方案2】:

    原来是因为我将 JSX 元素直接存储在 state 中。删除它并仅存储平铺值(纯 JS 字符串)修复了未正确更新状态的问题。太坑了!

    【讨论】:

      猜你喜欢
      • 2019-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      • 2021-03-22
      相关资源
      最近更新 更多