每次窗口渲染时如何生成随机数? 老 -----

问题描述

我正在使用 Less css 生成一个随机数,但它只生成一次随机数,直到浏览器再次刷新。

App.css

@color: blue;
// @random: (Math.round(Math.random() * 100));
@random: percentage(`Math.random()`);

.circle {
  position: absolute;
  border: solid 4px @color;
  border-radius: 50%;
  top: @random;
  left: @random;
  height: 3em;
  width: 3em;
  background-color: @color;
  animation: circleSize 0.5s;
}

App.js

function App() {
  const [date,setDate] = useState('')
  const [circleBoolean,setCircleBoolean] = useState(false);
  let random_number;
  useEffect(() => {
    const interval = setInterval(() => {
      doThings()
    },2000);
    return () => clearInterval(interval);
  },[circleBoolean]);

  function doThings() {
    setCircleBoolean(!circleBoolean);
    setDate(moment().format('MMMM Do YYYY,h:mm:ss a')) ;
    random_number = Math.random()*100;
    console.log("cirlce boolean :" + circleBoolean)
  }

  console.log("cirlce boolean outside:" + circleBoolean)


  return (
    <div className="App">
      <div className="bg">
        <div style={{top:random_number+"%"},{left:random_number+"%"}}  className={circleBoolean ? "circle" : ""}   />
        <div className="card">
          <p className="card-info">{date}</p>
        </div>
      </div>
    </div>
  );
}

在每次渲染期间添加删除圆类,并且在这些渲染期间随机数不会改变。如何让它在每次渲染时生成随机数?

解决方法

所以听着,我不知道你为什么要持有两个随机数(一个在 .css 文件中,另一个在组件本身中)。

当您在浏览器中刷新时,css 中的 @random 只会计算一次。您可以使用 styled-components 之类的东西根据组件中的状态使样式动态化。

另一种解决方法是在组件内覆盖(正如您所做的那样)左侧和顶部样式:

const App = () => {
  const [date,setDate] = useState('');
  const [circleBoolean,setCircleBoolean] = useState(false);
  const [randomNumber,setRandom] = useState();
  useEffect(() => {
    const interval = setInterval(() => {
      doThings();
    },2000);
    return () => clearInterval(interval);
  },[]);

  function doThings() {
    setRandom(() => {
      return Math.random() * 100;
    });
    setCircleBoolean((prev) => {
      return !prev;
    });
    setDate(moment().format('MMMM Do YYYY,h:mm:ss a'));
  }

  return (
    <div className="App">
      <div className="bg">
        <div style={{ top: randomNumber + '%',left: randomNumber + '%' }} className={circleBoolean ? 'circle' : ''} />
        <div className="card">
          <p className="card-info">{date}</p>
        </div>
      </div>
    </div>
  );
};

在这里,我更改了您的“样式”道具并将 random_number 移动到其自己的状态 randomNumber。

老 -----

首先,每当 circleBoolean 改变时,你的 useEffect 就会被触发,每两秒一次。 然后它会再次被调用并创建另一个间隔,依此类推。在这里,您需要一个 零依赖项 的数组用于您的 useEffect。这样,一旦组件第一次渲染,间隔将只创建一次。

好的,那么间隔函数将每两秒执行一次 setCircleBoolean 中的状态更改。这样做的正确方法(在这种情况下)是:

setCircleState((prev) => {
     return !prev;
});

这样,React 将等待状态变化并更准确地触发重新渲染。