简体   繁体   English

如何在依赖于另一个 state 的 useState 中设置初始 state

[英]How to set initial state in useState dependent on another state

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.有来自 API 的产品(在 state 'productsList' 中),我正在构建一个输入范围 slider,它将初始值设置为昂贵价格的值。

So, all I want is to use this line:所以,我只想使用这一行:

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

maxPricedProductPrice comes from the highest value in the productsList state. maxPricedProductPrice 来自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;

Do you have any trouble with updating the maxPriceInSlider inside the useEffect like the following?像下面这样更新maxPriceInSlider中的 maxPriceInSlider 有什么问题吗?

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.如果这对您不起作用,您可以隐藏范围输入,直到 API 呼叫结束,一旦您获得最高价格,然后在屏幕上显示它。

You can try a different approach.您可以尝试不同的方法。 After retrieving data from API and setting productsList also set maxPrieceInSlider at the same time like this:从 API 检索数据并设置 productsList 后,还同时设置了 maxPrieceInSlider,如下所示:

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.让我如果它有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM