Home > front end >  How to set initial state in useState dependent on another state
How to set initial state in useState dependent on another state

Time:09-30

There are products coming from API (in the state 'productsList') and I am working on building an input range slider that will have the initial value set to the value of the costly price.

So, all I want is to use this line:

const [maxPriceInSlider, setMaxPriceInSlider] = useState(maxPricedProductPrice);

maxPricedProductPrice comes from the highest value in the productsList state.

but it is not working.

any help is appreciated.

The complete code for the component is:

import React from "react";
import { useEffect, useState } from "react";

import axios from "axios";
import { ColorRing as Loader } from "react-loader-spinner";
import HeroGeneral from "../components/UI/HeroGeneral";
import BidItem from "../components/General/BidItem";
import "./bidslist.css";

const BidsList = () => {
  const [loading, setLoading] = useState(false);
  const [productsList, setProductsList] = useState([]);

  // get maximum priced product price
  const maxPricedProductPrice = Math.max(...productsList.map((prod) => prod.basePrice));

  const [minPriceInSlider, setMinPriceInSlider] = useState(0);

  // --------------------------------------------------------------------------------------

  // --------------- I WANT the maxPricedProductPrice to be set as initial state of maxPriceInSlider like this:
  //    const [maxPriceInSlider, setMaxPriceInSlider] = useState(maxPricedProductPrice);
  // But it is not working
  // productsList is coming from API
  const [maxPriceInSlider, setMaxPriceInSlider] = useState(0);

  const onMinPriceSliderChangeHandler = (e) => {
    setMinPriceInSlider(e.target.value);
  };
  const onMaxPriceSliderChangeHandler = (e) => {
    setMaxPriceInSlider(e.target.value);
  };

  // fetch all the prodcuts AFTER 1st page render
  useEffect(() => {
    // scroll to top on mount
    window.scrollTo(0, 0);
    setLoading(true);
    axios
      .get("http://localhost:5000/api/v1/products")
      .then((data) => {
        setProductsList(data.data.data.products);
        setLoading(false);
      })
      .catch((err) => {
        setLoading(false);
      });
  }, []);

  return (
    <div>
      <HeroGeneral />
      <div className="bidlist_page_content">
        <aside className="filter">
          <h2>Filter by</h2>
          <div className="filterby_cat">
            <h3>Category: </h3>
            <select name="c" id="">
              <option value="Electronics">Electronics</option>
              <option value="Others">Others</option>
            </select>
          </div>
          <div className="filterby_price">
            <h3>
              Start price:{" "}
              <input
                type="range"
                name="minPriceInSlider"
                value={minPriceInSlider}
                min="0"
                max={maxPricedProductPrice}
                onChange={onMinPriceSliderChangeHandler}
              />
              {minPriceInSlider}
            </h3>
            <h3>
              End price:{" "}
              <input
                type="range"
                name="maxPriceInSlider"
                value={maxPriceInSlider}
                min="0"
                max={maxPricedProductPrice}
                onChange={onMaxPriceSliderChangeHandler}
              />
              {maxPriceInSlider}
            </h3>
          </div>
        </aside>
        <div>
          <div className="divlist_grid_main">
            {loading && (
              <Loader
                visible={true}
                height="100"
                width="100"
                ariaLabel="blocks-loading"
                wrapperStyle={{}}
                wrapperClass="blocks-wrapper"
                colors={["#212529"]}
              />
            )}
            {!loading && productsList.length === 0 && "No products found!"}
            {productsList.map((prod) => (
              <BidItem
                key={prod._id}
                description={prod.description}
                category={prod.category}
                name={prod.name}
                closesAt={prod.closesAt}
                imgURL={prod.imageURL}
                prodId={prod._id}
                bPrice={prod.basePrice}
              />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export default BidsList;

CodePudding user response:

Do you have any trouble with updating the maxPriceInSlider inside the useEffect like the following?

useEffect(() => {
    // scroll to top on mount
    window.scrollTo(0, 0);
    setLoading(true);
    axios
      .get("http://localhost:5000/api/v1/products")
      .then((data) => {
        setProductsList(data.data.data.products);
        const tempProducts = data.data.data.products;
        const maxPricedProductPrice = Math.max(...tempProducts.map((prod) => prod.basePrice));
        // update the max price here
        setMaxPriceInSlider(maxPricedProductPrice);
        setLoading(false);
      })
      .catch((err) => {
        setLoading(false);
      });
  }, []);

If that doesn't work for you, you can hide the range input until the API call ends and once you have the max price then show that in the screen.

CodePudding user response:

You can try a different approach. After retrieving data from API and setting productsList also set maxPrieceInSlider at the same time like this:

axios
      .get("http://localhost:5000/api/v1/products")
      .then((data) => {
        const maxPricedProductPrice = Math.max(...productsList.map((prod) => prod.basePrice));
        setProductsList(data.data.data.products);
        setMaxPriceInSlider(maxPricedProductPrice);
        setLoading(false);
      })
      .catch((err) => {
        setLoading(false);
      });

this is much more efficient because if you keep getting the max price operation at the beginning of your code like you did, it will hinder your app because each time react re-renders your component, this operation will keep executing again and again needlessly.

let me if it works.

  • Related