I have this component:
export default function ThirdSlide({ userTopArtistsAllTime }) {
const newref = useRef();
const { items } = userTopArtistsAllTime;
let genresObj = {};
let genres = [];
useEffect(() => {
getData();
createPie(genresObj);
}, [genresObj]);
const getData = () => {
items
? items.map((item) => {
genres.push(item.genres[0]);
genres.push(item.genres[1]);
})
: console.log("null");
if (genres.length > 1) {
for (let value in genres) {
let key = genres[value];
genresObj[key] ? genresObj[key]++ : (genresObj[key] = 1);
}
}
};
const createPie = (data) => {
....
};
return (
<React.Fragment>
<Background>
<div>
<span>What genres do you favorite artists fit in?</span>
</div>
<div
style={{ marginLeft: "50px", marginTop: "200px" }}
ref={newref}
></div>
</Background>
</React.Fragment>
);
}
The createPie(data) function just creates a chart in D3 and its working okay. The problem that I have is that react renders the SVG 5 times instead of just once and I think it has to do with useEffect and my props?
How can I restructure this code so createPie is called just once?
Because useEffect
dependency is genresObj
and in every render a new empty object is created by let genresObj = {};
so useEffect
run in every render.
You can depend useEffect
on items
and move variables inside useEffect scope.
useEffect(() => {
let genresObj = {};
let genres = [];
getData();
createPie(genresObj);
}, [items]);
However, for code actually works you need pass down parameters to getData
as well.
Adding more color to Makan's answer.
useEffect
will rerun the effect every time any one of its dependencies changes . To know if a dependency changes, useEffect uses ===
to determine whether two consecutive dependencies are equal.
In JS, {} === {}
evaluates to false
. So in the eyes of useEffect
, genresObj
is different every time, causing it to recall your D3 logic.
Changing useEffect to depend on userTopArtistsAllTime
, like has been suggested, makes sense. With that change, you will recall the effect as often as userTopArtistsAllTime
changes ===
equality. If you make that change and you still see the useEffect
firing too often, check to see what logic is constructing userTopArtistsAllTime
.
Now, it seems that you currently have a bug with your getData
implementation. Make it a pure function of its arguments to correctly handle side effects.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.