Stack Overflow Asked by Baudoin Michael on August 20, 2020
I’d like to sort through an array of objects.
But I’m stuck here for a while: when the props filterActivated
changes, the state is updated (verified in the browser’s react dev tool), but there is no re-rendering.
I don’t understand why the view is not re-rendered, even when the ideasArray
is getting updated.
This is my component :
import React, { useState, useEffect } from 'react'
// Components
import Idea from './Idea'
const IdeasContainer = ({ filterActivated }) => {
const [ideasArray, setIdeasArray] = useState([]);
useEffect(() => {
const getIdeas = async () => {
try {
const response = await fetch("http://localhost:3004/api/ideas")
const data = await response.json()
setIdeasArray(data)
} catch (err) {
console.error('getIdeas error: ', err, err.stack)
}
}
getIdeas();
}, []);
useEffect(() => {
const sorted = (array) => {
let newArray = array.sort(function (a, b) {
if (filterActivated === 'scoreAsc') {
return a.score - b.score
}
else if (filterActivated === 'scoreDesc') {
return b.score - a.score
}
});
setIdeasArray(newArray);
}
sorted(ideasArray);
}, [filterActivated, ideasArray]);
return (
<div className="ideasContainer">
{
ideasArray.map((idea, index) => {
return <Idea key={index} dataIdea={idea} />
})
}
</div>
)
}
export default IdeasContainer;
Firstly, your useEffect
has a few issues:
Don't reference the ideasArray as a useEffect
dependency if you're setting that value inside the useEffect
. That will cause infinite loops because when you set the value, the `useEffect gets called again, which sets the value, which calls it again, which sets the value... and so on. If you depend on the previous value to set the new value, pass a setter function to the setIdeasArray function, for example:
useEffect(() => {
setIdeasArray(oldValue =>
[...oldValue].sort((a, b) => {
if (filterActivated === "scoreAsc") {
return a.score - b.score;
} else if (filterActivated === "scoreDesc") {
return b.score - a.score;
}
})
);
}, [filterActivated]);
Notice how I'm also spreading the oldValue
into a new array before sorting. This is because Array.sort
is not reliably immutable, so in certain situations it will mutate the original data, which we do not want in React.
If state changes, there is always a re-render. React's render cycle is not the same as the DOM changing, but React will still run the component render cycle if props or state changes.
The issue you're having is due to using the index
as a key
for each idea. Using indexes as keys is a really bad idea.
The whole point of keys is to allow React to identify items in an array without it having to re-render them, so by using the indexes, what you're essentially saying is that the first item (always index 0
) never changes. Yes, your state is re-ordered, but React sees that the keys have not changed order, so it does not change the DOM to match.
Keys need to be related to the item (such as a unique id), so that React can identify that item by something unrelated to "its position within an array".
Correct answer by JMadelaine on August 20, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP