如何绕过无意义的检查array.filter

时间:2019-07-12 00:18:26

标签: javascript reactjs

我有2个输入用于过滤arrProd(请参见下面的代码)。在FormSubmit函数中,我首先检查price.minPrice和price.maxPrice的值是否为有效数字而不是空字符串。经过这些检查之后,只能有两个选择:用户输入并输入数字或将字段留空。然后,我检查数字是否已经开始,然后对数组进行过滤。在过滤循环中,多次检查该值是没有意义的。我怎样才能只检查一次?

import React, { Fragment, useCallback, useState } from "react";
import ReactDOM from "react-dom";

const arrProd = [
  {
    price: "5.75",
    sold: "100"
  },
  {
    price: "2.36",
    sold: "15"
  },
  {
    price: "5.48",
    sold: "20"
  },
  {
    price: "4.49",
    sold: "200"
  },
  {
    price: "3.15",
    sold: "258"
  },
  {
    price: "9.99",
    sold: "479"
  },
  {
    price: "4.8",
    sold: "147"
  },
  {
    price: "8",
    sold: "951"
  },
  {
    price: "4.27",
    sold: "753"
  },
  {
    price: "2.46",
    sold: "852"
  },
  {
    price: "4.99",
    sold: "742"
  },
  {
    price: "3.49",
    sold: "10"
  },
  {
    price: "2",
    sold: "26"
  },
  {
    price: "3.83",
    sold: "39"
  },
  {
    price: "9.98",
    sold: "47"
  },
  {
    price: "6.77",
    sold: "96"
  }
];

function App() {
  const [price, setPrice] = useState({ maxPrice: "", minPrice: "" });
  const [sold, setSold] = useState("");
  const [processingProd, setProcessingProd] = useState([]);
  const [checkInput, setCheckInput] = useState({
    checkPrice: false,
    checkSold: false
  });

  const PriceMaxMin = useCallback(({ target: { value, name } }) => {
    name === "maxPrice"
      ? setPrice(({ minPrice }) => ({ maxPrice: value, minPrice }))
      : setPrice(({ maxPrice }) => ({ minPrice: value, maxPrice }));
  }, []);
  console.log(processingProd);
  const FormSubmit = event => {
    if (checkInput.checkPrice) setCheckInput({ checkPrice: false });
    const checkPrice =
      price.minPrice === "" && price.minPrice === ""
        ? "initial values"
        : +price.maxPrice >= +price.minPrice &&
          price.minPrice !== "" &&
          !Number.isNaN(+price.maxPrice) &&
          !Number.isNaN(+price.minPrice);
    const checkSold = sold === "" ? "initial values" : !Number.isNaN(+sold);

    if (!checkPrice || !checkSold) {
      setCheckInput({ checkPrice: !checkPrice, checkSold: !checkSold });
      return false;
    }

    const x = arrProd.filter(prod => {
      const filterPrice =
        checkPrice === "initial values"
          ? true
          : +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
      const filterSold =
        checkSold === "initial values" ? true : +sold >= +prod.sold;

      return filterPrice && filterSold;
    });
    setProcessingProd(x);
    event.preventDefault();
  };

  return (
    <Fragment>
      <form onSubmit={FormSubmit}>
        {checkInput.checkPrice && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Min"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={price.minPrice}
          onChange={PriceMaxMin}
        />
        {"Max"}
        <input
          type={"text"}
          name={"maxPrice"}
          size={6}
          maxLength={10}
          value={price.maxPrice}
          onChange={PriceMaxMin}
        />
        {checkInput.checkSold && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Sold"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={sold}
          onChange={({ target: { value, name } }) => setSold(value)}
        />
        <input type="submit" title={"Submit price range"} value={"Go"} />
      </form>
    </Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

1 个答案:

答案 0 :(得分:3)

在阅读完您的问题后我不确定,但是我认为您是指checkPrice === "initial values"checkSold === "initial values"在此过滤器中反复测试的方式:

const x = arrProd.filter(prod => {
  const filterPrice =
    checkPrice === "initial values"
      ? true
      : +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
  const filterSold =
    checkSold === "initial values" ? true : +sold >= +prod.sold;

  return filterPrice && filterSold;
});

实际上,只需测试一次就足够了。 因此,让我们将整个测试移到过滤器之外。

const x = arrProd.filter(
    checkPrice === "initial values"
        ? checkSold === "initial values"
            ? prod => true
            : prod => +sold >= +prod.sold
        : checkSold === "initial values"
            ? prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice
            : prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice && +sold >= +prod.sold
);

请注意,我们现在有四个单独的谓词。它们之间有代码重复。这可以通过使用命名函数来消除。

const acceptAny = prod => true;
const acceptIfPriceInRange = prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
const acceptIfSoldInRange = prod => +sold >= +prod.sold;
const acceptIfBothInRange = prod => acceptIfPriceInRange(prod) && acceptIfSoldInRange(prod);

const x = arrProd.filter(
    checkPrice === "initial values"
        ? checkSold === "initial values" ? acceptAny : acceptIfSoldInRange
        : checkSold === "initial values" ? acceptIfPriceInRange : acceptIfBothInRange
);

完整的源文件:

import React, { Fragment, useCallback, useState } from "react";
import ReactDOM from "react-dom";

const arrProd = [
  {
    price: "5.75",
    sold: "100"
  },
  {
    price: "2.36",
    sold: "15"
  },
  {
    price: "5.48",
    sold: "20"
  },
  {
    price: "4.49",
    sold: "200"
  },
  {
    price: "3.15",
    sold: "258"
  },
  {
    price: "9.99",
    sold: "479"
  },
  {
    price: "4.8",
    sold: "147"
  },
  {
    price: "8",
    sold: "951"
  },
  {
    price: "4.27",
    sold: "753"
  },
  {
    price: "2.46",
    sold: "852"
  },
  {
    price: "4.99",
    sold: "742"
  },
  {
    price: "3.49",
    sold: "10"
  },
  {
    price: "2",
    sold: "26"
  },
  {
    price: "3.83",
    sold: "39"
  },
  {
    price: "9.98",
    sold: "47"
  },
  {
    price: "6.77",
    sold: "96"
  }
];

function App() {
  const [price, setPrice] = useState({ maxPrice: "", minPrice: "" });
  const [sold, setSold] = useState("");
  const [processingProd, setProcessingProd] = useState([]);
  const [checkInput, setCheckInput] = useState({
    checkPrice: false,
    checkSold: false
  });

  const PriceMaxMin = useCallback(({ target: { value, name } }) => {
    name === "maxPrice"
      ? setPrice(({ minPrice }) => ({ maxPrice: value, minPrice }))
      : setPrice(({ maxPrice }) => ({ minPrice: value, maxPrice }));
  }, []);
  console.log(processingProd);
  const FormSubmit = event => {
    if (checkInput.checkPrice) setCheckInput({ checkPrice: false });
    const checkPrice =
      price.minPrice === "" && price.minPrice === ""
        ? "initial values"
        : +price.maxPrice >= +price.minPrice &&
          price.minPrice !== "" &&
          !Number.isNaN(+price.maxPrice) &&
          !Number.isNaN(+price.minPrice);
    const checkSold = sold === "" ? "initial values" : !Number.isNaN(+sold);

    if (!checkPrice || !checkSold) {
      setCheckInput({ checkPrice: !checkPrice, checkSold: !checkSold });
      return false;
    }

    const acceptAny = prod => true;
    const acceptIfPriceInRange = prod => +prod.price > +price.minPrice && +prod.price < +price.maxPrice;
    const acceptIfSoldInRange = prod => +sold >= +prod.sold;
    const acceptIfBothInRange = prod => acceptIfPriceInRange(prod) && acceptIfSoldInRange(prod);

    const x = arrProd.filter(
        checkPrice === "initial values"
            ? checkSold === "initial values" ? acceptAny : acceptIfSoldInRange
            : checkSold === "initial values" ? acceptIfPriceInRange : acceptIfBothInRange
    );

    setProcessingProd(x);
    event.preventDefault();
  };

  return (
    <Fragment>
      <form onSubmit={FormSubmit}>
        {checkInput.checkPrice && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Min"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={price.minPrice}
          onChange={PriceMaxMin}
        />
        {"Max"}
        <input
          type={"text"}
          name={"maxPrice"}
          size={6}
          maxLength={10}
          value={price.maxPrice}
          onChange={PriceMaxMin}
        />
        {checkInput.checkSold && (
          <div>{"Please provide a valid price range"}</div>
        )}
        {"Sold"}
        <input
          type={"text"}
          name={"minPrice"}
          size={6}
          maxLength={10}
          value={sold}
          onChange={({ target: { value, name } }) => setSold(value)}
        />
        <input type="submit" title={"Submit price range"} value={"Go"} />
      </form>
    </Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

免责声明:我没有测试完整的代码;我会留给你。