Home > front end >  React UseState not updating immediately
React UseState not updating immediately

Time:12-28

I'm trying to build a react landing page shows the different screen based on the props.products. If products exists in the API call response, it'll update the global state of products and update products from null to an array. The problem I face here is that even though the state is updated (I've checked through Redux Dev Tools), the pages doesn't show the correct screen. The problem occurs when trying to load screen type 3.

function LandingPage(props) {
  const [eligibleProducts, setEligibleProducts] = useState([]);
  const [screenType, setScreenType] = useState();
  const [url, setUrl] = useState("");
  const [message, setMessage] = useState("");
  const [loading, setLoading] = useState(false);
  const [isActive, setisActive] = useState(false);

  const { pocBusinessEmail, pocBusinessName } = props;

  useEffect(() => {
    handleEligibleProducts();
  }, []);

  useEffect(() => {
    console.log('count')
    if(props.products && (props.products.filter((product) => product.productStatus === 2).length > 0)){
      console.log("init")
      setisActive(true)
    }
  }, [props.products]);

  useEffect(() => {}, [props.eligibleProducts]);
  

  const handleEligibleProducts = async () => {
    setLoading(true);
    let data = {
      userType: 102,
    };
    data["email"] = window.localStorage.getItem("email");

    try {
      
      const res = await props.getEligibleProducts(data);
      const { statusCode, msgText, productList, Url } = res.data.responsePayload;
      let allEligibilityFlagZero = false;
      let noidforsome = false;
      if (Url.length != "") {
        setUrl(new URL(Url));
      }
     if(statusCode === 200){
          let data = {};
          data["employeeId"] = props.employeeId;
          data["products"] = null;
          await props.employeeProduct(data);
      } 

      if (productList) {
        setEligibleProducts(productList.map((product) => ({ ...product, selected: false })));
        allEligibilityFlagZero = productList.length && productList.every((product) => product.eligibilityFlag === 0);
       // noArcIdForSomeProduct = productList.length && productList.some((product) => !(product && (product.arcId || product.arcId !== null)));
      //  if(props.products){
      //     if((props.products.filter((product) => product.productStatus === 2).length > 0)){
      //       setisActive(true)
      //     }
      //   }
      

      
        }

      if (statusCode !== 200) {
        setScreenType(4);
        setMessage(msgText);
      } else if (!(productList && productList.length !== 0) || allEligibilityFlagZero) {
        setScreenType(1);
      } else if (!isActive) {
        setScreenType(2);
      } else {
        setScreenType(3);
      }
      setLoading(false);
      
    } catch (error) {
      setLoading(false);
      console.log("big error: "   error);
    }
  };
  let navigate = useNavigate();
  const routeChange = (direction) => {
    let path = direction;
    navigate(path);
  };

  const getProperScreen = () => {
    switch (screenType) {
      case 1:
        return <ScreenOne eligibleProducts={eligibleProducts} />;

      case 2:
        return <ScreenTwo eligibleProducts={eligibleProducts} handleSelectProduct={handleSelectProduct} selectUnSelectAllProduct={selectUnSelectAllProduct} />;

      case 3:
        return <ScreenThree eligibleProducts={eligibleProducts} handleSelectProduct={handleSelectProduct} selectUnSelectAllProduct={selectUnSelectAllProduct} products= {props.products} />;

      case 4:
        return <ErrorScreen message={message} />;
      
      default: 
        return <ScreenOne eligibleProducts={eligibleProducts} />;
    }
  };

  if (loading) return <Loader />;

  return (
    <>
      <Container maxWidth={false}>
        <Grid container sx={{ justifyContent: "space-between", p: "1rem 2rem" }}>
          <Grid item>
            <Box>
              <Header registrationBool={true} loggedInBool={true} pocBusinessEmail={pocBusinessEmail} pocBusinessName={pocBusinessName} />
            </Box>
          </Grid>
        </Grid>
      </Container>
      {getProperScreen()}
      {<FooterButtonContainer title="Apply Now" handleApplyNow={handleApplyNow} eligibleProducts={eligibleProducts} />}
      <Footer />
    </>
  );
}

export default LandingPage;

CodePudding user response:

The only issue I'm seeing is that handleEligibleProducts depends on isActive and props but the effect hook that calls it has no dependencies.

It's best not to call functions defined within the component within an effect hook as the dependency graph gets messy. Instead, define the function within the effect hook itself and make sure all dependencies are listed.

const { products, getEligibleProducts, employeeId, employeeProduct } = props;

useEffect(() => {
  const handleEligibleProducts = async () => {
    // ...
  };

  handleEligibleProducts();
}, [
  isActive,
  getEligibleProducts,
  products,
  getEligibleProducts,
  employeeId,
  employeeProduct,
]);

Edit cranky-satoshi-se5pws

As F.Müller mentioned, you should ideally use a linter that points out these issues.

  • Related