如何优化React中的Search Filter组件

问题描述 投票:0回答:1

这是搜索过滤器组件的代码,用户可以通过在输入字段中键入字母来查找产品。我想知道我可以添加哪些改进。我正在考虑将一些逻辑删除到自定义挂钩中,但认为没有必要,因为我只使用它一次。

附注我知道对于此类问题最好使用 Stack Exchange 之类的东西,但我想得到答案。

成分:

export const SearchItems = ({
  openBackdrop,
  setOpenBackDrop,
}: SearchItemsProps) => {
  const theme = useTheme();
  const [searchQ, setSearchQ] = useState<string>("");
  const [isScrollDisabled, setIsScrollDisabled] = useState<boolean>(false);
  const [products, setProducts] = useState<Product[]>([]);
  const [productsByQ, setProductsByQ] = useState<Product[]>([]);

  useEffect(() => {
    const getProducts = async () => {
      try {
        const productsRef = await getDocs(collection(db, "products"));
        const products = productsRef.docs.map((doc) => ({
          ...doc.data(),
        }));
        const flattenData: Product[] = products.flatMap(
          (product) => product.data
        );
        setProducts(flattenData);
      } catch (error: any) {
        console.log(error.message);
      }
    };

    getProducts();
  }, []);

  const handleFilterProductsByQ = useMemo(
    () =>
      debounce((searchQ: string) => {
        const filteredData = products.filter((product) =>
          product.name.toLowerCase().includes(searchQ.toLowerCase())
        );
        setProductsByQ(filteredData);
      }, 300),
    [products]
  );

  useEffect(() => {
    handleFilterProductsByQ(searchQ);
  }, [searchQ]);

  useEffect(() => {
    isScrollDisabled
      ? (document.body.style.overflow = "hidden")
      : (document.body.style.overflow = "auto");

    return () => {
      document.body.style.overflow = "auto";
    };
  }, [isScrollDisabled]);

  const handleInputFocus = () => {
    window.scrollTo({ top: 0, behavior: "auto" });
    setIsScrollDisabled(true);
    setOpenBackDrop(true);
  };

  const handleOutsideClick = () => {
    setOpenBackDrop(false);
    setIsScrollDisabled(false);
    setSearchQ("");
  };

  return (
    <OutsideClickHandler onOutsideClick={handleOutsideClick}>
      <Box position="relative">
        <OutlinedInput
          type="text"
          placeholder="Search Item…"
          value={searchQ}
          onChange={(e) => setSearchQ(e.target.value)}
          onFocus={handleInputFocus}
          startAdornment={
            <InputAdornment
              position="start"
              sx={{
                color: theme.palette.primary.main,
                fontSize: "1.2rem",
              }}
            >
              <FiSearch />
            </InputAdornment>
          }
          endAdornment={
            <InputAdornment position="end">
              <IconButton
                edge="end"
                onClick={() => setSearchQ("")}
                sx={{
                  color: theme.palette.secondary.light,
                  cursor: "pointer",
                  fontSize: "0.1rem",
                }}
              >
                {searchQ !== "" && <CloseIcon />}
              </IconButton>
            </InputAdornment>
          }
          sx={{
            borderRadius: "0.8rem",
            border: "none",
            backgroundColor:
              openBackdrop === true ? "#f9fafb" : theme.palette.primary.light,
            zIndex: openBackdrop === true ? 9999 : "none",
            "& .MuiOutlinedInput-notchedOutline": {
              border: "none",
            },
          }}
        />
        {searchQ.length !== 0 && (
          <SearchResult searchQ={searchQ} productsByQ={productsByQ} />
        )}
      </Box>
    </OutsideClickHandler>
  );
};
reactjs
1个回答
0
投票

你不需要这个

const [productsByQ, setProductsByQ] = useState<Product[]>([]);
以及围绕它的整个逻辑。所以你已经有了一个保存
products
的状态和一个用于
search term
的状态。

每次您的搜索词发生变化,它都会触发组件重新渲染,因此您可以直接使用您的搜索词和产品,如下所示:

{
  searchQ.length !== 0 && (
    <SearchResult
      searchQ={searchQ}
      productsByQ={products.filter((product) =>
        product.name.toLowerCase().includes(searchQ.toLowerCase())
      )}
    />
  )
}

然后您可以移动搜索词的去抖逻辑,这样您就不会按每个击键进行过滤

© www.soinside.com 2019 - 2024. All rights reserved.