Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
343 views
in Technique[技术] by (71.8m points)

javascript - How to generate random number each time window renders?

I am using Less css to generate a random number but it generates a random number only once until the browser refreshes again .

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;
}

and

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>
  );
}

The circle class is added and removed during each render and the random number is not changing during those renders . How do I make it generate random number during each render?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So listen, I don't know why you're holding two randoms (one in the .css file and other in the component itself).

The @random in your css will only evaluate once, when you do a refresh in the browser. You use something like styled-components to make your styles dynamic based on states in your component.

The other workaround is to override (as you are doing) the left and top styles from within the component:

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>
  );
};

Here, I changed your "style" prop and moved the random_number into its own state randomNumber.

OLD -----

First your useEffect is triggered whenever circleBoolean is changed, each two seconds. Then it'll be called again and create another interval, and so on. Here, you need an array of zero dependencies for your useEffect. That way the interval will be created just once, once the component renders the first time.

Okey, then each two seconds the interval function will execute a state change in setCircleBoolean. The correct way to do so (in this case) would be:

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

This way, React will wait for the state change and triggers the re-render more accurately.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...