这是搜索过滤器组件的代码,用户可以通过在输入字段中键入字母来查找产品。我想知道我可以添加哪些改进。我正在考虑将一些逻辑删除到自定义挂钩中,但认为没有必要,因为我只使用它一次。
附注我知道对于此类问题最好使用 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>
);
};
你不需要这个
const [productsByQ, setProductsByQ] = useState<Product[]>([]);
以及围绕它的整个逻辑。所以你已经有了一个保存 products
的状态和一个用于 search term
的状态。
每次您的搜索词发生变化,它都会触发组件重新渲染,因此您可以直接使用您的搜索词和产品,如下所示:
{
searchQ.length !== 0 && (
<SearchResult
searchQ={searchQ}
productsByQ={products.filter((product) =>
product.name.toLowerCase().includes(searchQ.toLowerCase())
)}
/>
)
}
然后您可以移动搜索词的去抖逻辑,这样您就不会按每个击键进行过滤