【问题标题】:How to stop certain react components from rerendering after the state of another component changes如何在另一个组件的状态更改后阻止某些反应组件重新渲染
【发布时间】:2022-11-29 06:05:34
【问题描述】:

所以我想渲染 x 个圆圈。每个圆圈都呈现在屏幕上的随机位置。它们中的每一个都有一个值参数,这是将添加到左上角显示的总点数的数量。单击一个圆圈后,它应该将其值添加到计数中并消失。它做了它应该做的事情,但是在点击时,所有其他圆圈都会重新呈现一个新的随机位置,这是他们不应该做的。初始设置的 x 和 y 位置应该为每个圆圈生成一次并保持这样。我如何防止这种情况发生? 这是我的代码:

import { useState } from "react";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);
  let ctr = 0;

  function getRandom(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min) + min);
  }

  function renderCircle(xPos, yPos, color, value) {
    ctr++;

    const handleClick = (id) => () => {
      setCount(count + value);
      const el = document.getElementById(id);
      el.style.visibility = "hidden";
    };
    return (
      <div>
        {
          <svg
            className="circle"
            id={ctr}
            onClick={handleClick(ctr)}
            style={{
              left: `calc(${xPos}vw - 60px)`,
              top: `calc(${yPos}vw - 60px)`,
              position: "absolute",
            }}
          >
            <circle cx={30} cy={30} r={30} fill={color} />
          </svg>
        }
      </div>
    );
  }

  function renderCircles(amount) {
    const arr = [];
    for (let i = 0; i < amount; i++) {
      let circle = renderCircle(
        getRandom(3, 53),
        getRandom(3, 40),
        Object.keys(Color)[
          Math.floor(Math.random() * Object.keys(Color).length)
        ],
        getRandom(1, 100)
      );
      arr.push(circle);
    }
    return arr;
  }

  return (
    <div className="App">
      <div className="App-game">{renderCircles(15)}</div>
      <div className='App-currency' style={{color: "black", fontSize: 80}}>
        {count}
      </div>
    </div>
  );
}

export default App;

class Color {
  static Green = new Color("green");
  static Blue = new Color("blue");
  static Yellow = new Color("yellow");
  static Red = new Color("red");
  static Pink = new Color("pink");
  static Orange = new Color("orange");

  constructor(name) {
    this.name = name;
  }
  toString() {
    return `Color.${this.name}`;
  }
}

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您应该将圆圈保存在状态变量中

      const [circles] = useState(renderCircles(15));
    
      return (
        <div className="App">
          <div className="App-game">{circles}</div>
          <div className="App-currency" style={{ color: 'black', fontSize: 80 }}>
            {count}
          </div>
        </div>
      );
    

    您还遇到了环绕圆圈的 svg 大小的问题 - 它更大,因此可以在不实际单击圆圈的情况下触发点击事件。也不需要计数器和分配 id,onClick 事件提供了被点击的目标。

      function renderCircle(xPos, yPos, color, value) {
        function handleClick(e) {
          setCount((prev) => prev + value);
          e.target.style.visibility = 'hidden';
        }
        return (
          <svg
            className="circle"
            onClick={handleClick}
            style={{
              left: `calc(${xPos}vw - 60px)`,
              top: `calc(${yPos}vw - 60px)`,
              width: 60,
              height: 60,
              position: 'absolute',
            }}
          >
            <circle cx={'50%'} cy={'50%'} r={'50%'} fill={color} />
          </svg>
        );
      }
    

    闪电战:https://stackblitz.com/edit/react-ts-b6jddu?file=App.tsx


    请注意,在增加计数时,我还将 setCount 参数更改为回调函数。当新值依赖于以前的值时,您应该养成这样做的习惯。否则你可能会遇到错误。

    例如:

    const {useState} = React;
    
    function App() {
      // count is a local variable, which the value of the state gets copied onto here
      const [count, setCount] = useState(0);
      
      function incrementThreeTimesWrong() {
        // count is 0 here
        setCount(count + 1); // sets to 0 + 1
        setCount(count + 1); // sets to 0 + 1
        setCount(count + 1); // sets to 0 + 1
        // count is still 0 here - setCount does not mutate the local variable
        // However setCount triggers a rerender, which will update the local variable to 1
      }
    
      function incrementThreeTimesRight() {
        setCount(prev => prev + 1); // sets to 0 + 1
        setCount(prev => prev + 1); // sets to 1 + 1
        setCount(prev => prev + 1); // sets to 2 + 1
      }
      
      return (
        <div>
          <p>{count}</p>
          <button onClick={incrementThreeTimesWrong}>Increment three times the wrong way</button>
          <br/>
          <button onClick={incrementThreeTimesRight}>Increment three times the right way</button>
        </div>);
    }
    
    ReactDOM.createRoot(
        document.getElementById("root")
    ).render(
        <App />
    );
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

    【讨论】:

      猜你喜欢
      • 2017-03-24
      • 2022-07-08
      • 1970-01-01
      • 2023-03-22
      • 2021-01-27
      • 1970-01-01
      • 2021-06-20
      • 2022-07-12
      • 2020-10-07
      相关资源
      最近更新 更多