I am using a function that takes an array as input and returns a shuffled array. When i return the shuffled array , the UI is not getting repainted. Code below –
import { useState } from "react";
function App() {
const [items, setItems] = useState([
"Amit",
"Ashok",
"Alok",
"Vijay",
"Kumar",
"Raju",
]);
console.log("App component is rendered");
function shuffle(array) {
let currentIndex = array.length;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
let randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex],
array[currentIndex],
];
}
//
console.log(array);
return array;
//return [...array];
}
console.log(items);
return (
<>
<button onClick={() => setItems(shuffle(items))}>Shuffle</button>
{items?.map((item) => (
<p key={item}>{item}</p>
))}
</>
);
}
export default App;
If i return the array using the spread operator , the UI is getting rendered again. Can anyone explain what is the reason for this.
2
Answers
When you use the spread operator to return a new array, it creates a new array object with a different reference. React re-renders components when there is a change in state or props. It checks if the reference of the state object has changed. This is why React re-renders the UI when you return the array using the spread operator.
So re-rendering can happen for two reasons
If you directly modify an existing array (i.e., mutate it), the reference to that array remains the same. Since React uses shallow comparison for state updates, it doesn’t detect any changes and therefore doesn’t trigger a re-render.
Or if you create a new array using the spread operator (or any other method), a new array with a different reference is created. React detects that the reference to the state object has changed, so it triggers a re-render.
So instead of returning the array using a spread operator, you can even create a new one like below
React will not detect the change in object in place, instead you need to create an array and let set in state so that react will detect change and re-render.
let shuffledArray = array.slice();
or
let shuffledArray = [...array];
to create new array.
add the line and suffle this, then return this suffeled array back.