I am having trouble on changing count value in React.
I have dynamic set, and I want to render the size of set whenever it changes!
So I want to keep update count variable to ratedSet.size whenever the ratedSet's size changes.
I get it that useSet wont render again until whenever the thing ends so I tried to use useEffect and it still won't work. I think i am not using it correctly.
How can I show the size of set whenever it changes ?
Below are my Code. I added few comments on what i tried to do:
import React, { useEffect, useState } from "react";
import BoardCardMain from "./component/BoardCardSurvey";
//other import statements
export default function Survey() {
const [gameList, setGameList] = useState<Game[]>([]);
const [count, setCount] = useState(0); //This is the count variable that I want to keep update
const [width] = useState(window.innerWidth);
let ratedSet = new Set(); //this is the set that I want to keep track of
let cnt = 0;
useEffect(() => {
setGameList(tempData.gameList);
}, []);
// I tried to do this but im not even close to answer...
useEffect(() => {
setCount(ratedSet.size);
}, [ratedSet.size]);
//This is the part I am changing the size of set dynamically
//I am getting gameNo and score from child tsx, and am updating the set based on it
const countHandler = (ratedGameNo: number, score: number) => {
if (score > 0) {
ratedSet.add(ratedGameNo);
} else {
ratedSet.forEach((item) => {
if (item === ratedGameNo) {
ratedSet.delete(item);
}
});
}
//So here, if I console.log(ratedSet.size), it gives me correct values.
//but if i do setCount(ratedSet.size) it only updates once and never change again
};
return (
<>
SIZE IS : {count}
SIZE IS : {ratedSet.size}
None of them works
<Box> I am updating my set with below map : </Box>
<Container style={{ marginTop: 20, padding: 10 }}>
<Grid container spacing={2}>
{gameList.map((game) => (
<BoardCardMain
key={game.gameNo}
game={game}
parentCallback={countHandler}
></BoardCardMain>
))}
</Grid>
</Container>
</>
);
}
const tempData = {
gameList: [
{
gameNo: 1,
gameImg:
"https:/",
},
{
gameNo: 12,
gameImg:
"https://",
},
{
gameNo: 2,
gameImg:
"https://r",
},
],
};
CodePudding user response:
Because ratedSet
is not a state of the component. Mutating the set will NOT cause the component re-render. So the useEffect(() => {}, [ratedSet.size])
hook will not execute again.
I think there are two solutions:
- Force updates the component when any changes are made to the
ratedSet
.
const forceUpdate: () => void = React.useState()[1].bind(null, {});
- Maintain the
ratedSet
as a state, you can create a custom hook like useSet. (Recommend)
And you declare the ratedSet
inside function component may be wrong. Because every time component rendering, you will create a new one.
CodePudding user response:
I tried use Effect and forceUpdate and those two did not work. And i tried using useSet and somehow I wanst able to import it tho I installed the package.
Instead of using useSet, I set rateSet as state as suggested and it works now :D
I removed Set and used array instead*
const [count, setCount] = useState(0);
const [ratedGame, setRatedGame] = useState<number[]>([]);
const countHandler = (ratedGameNo: number, score: number) => {
if (score > 0) {
if (ratedGame.length === 0) {
ratedGame.push(ratedGameNo);
setCount(count 1);
} else {
let found = ratedGame.includes(ratedGameNo) ? true : false;
if (found) {
} //do nothing
else {
setCount(count 1);
ratedGame.push(ratedGameNo);
}
}
} else if (score === 0) {
setCount(count - 1);
var index = ratedGame.indexOf(ratedGameNo);
if (index !== -1) {
ratedGame.splice(index, 1);
}
}
};