I want to create an array of non-overlapping random numbers with a length of 20.
However, when executed, the array is not complete and sometimes an error message "Too many re-renders" appears.
import React, {useState, useEffect} from "react";
const Ques = () => {
const [randArr, setRandArr] = useState([]);
const [randNum, setRandNum] = useState(0);
let rand = Math.floor(Math.random() * (19-0));
if(randArr.length !== 20 && randArr.includes(randNum) === true){
rand = Math.floor(Math.random() * (19-0));
setRandNum(rand)
}
useEffect(() =>{
setRandNum(rand);
setRandArr([...randArr, randNum]);
console.log("randNum : ", randNum);
console.log("randArr : ", randArr);
},[rand]);
return (
<div>
<button>Start</button>
</div>
);
};
export default Ques;
CodePudding user response:
As has been pointed out in comments, you are declaring a new rand
value each render cycle and using it as a dependency for an useEffect
hook which then also enqueues a state update and triggers a rerender... repeat ad nauseam.
Instead of trying to iterate and populate an array with "random" numbers by "guessing" if they've already been selected, it'd be better to start with an array of [1..20]
and "shuffle" it.
Example:
const res = Array.from({ length: 20 }, (_, i) => i 1).sort(() => Math.random() - 0.5);
console.log(res.join(","));
You can just initialize your state to this value. No need for any loops and useEffect
hooks.
const [randArr, setRandArr] = useState(
Array.from({ length: 20 }, (_, i) => i 1).sort(() => Math.random() - 0.5)
);
CodePudding user response:
import React, { useState, useEffect } from "react";
const App = () => {
const [random, setRandom] = useState([]);
const getRandom = () => Math.floor(Math.random() * (19 - 0));
useEffect(() => {
const arr = [];
for (let i = 0; i < 20; i ) {
arr.push(getRandom());
}
setRandom(arr);
console.log(arr);
}, []);
return (
<div>
<div>{random.join(",")}</div>
<button>Start</button>
</div>
);
};
export default App;