Home > Mobile >  How to update useState() when value changes in React
How to update useState() when value changes in React

Time:03-31

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:

  1. Force updates the component when any changes are made to the ratedSet.
const forceUpdate: () => void = React.useState()[1].bind(null, {});
  1. 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);
      }
    }
  };
  • Related