React Router中基于searchParams实现多值产品筛选的问题求助
React Router中基于searchParams实现多值产品筛选的问题求助
各位大佬好~我现在用react-router做一个产品筛选网站,目前能正常获取到searchParams(比如color: black),但每次选不同颜色的时候,新选的值会直接替换掉当前选中的那个,我想要实现多选功能,比如同时选中black、grey这类多个值。
我试过用searchParams.getAll()但没搞成功,下面是我的Products组件和FilterNav组件的代码,麻烦帮忙看看哪里出问题了,怎么调整才能实现多值筛选?
Products组件代码
import { useState } from "react"; import { Link, useSearchParams, useLoaderData } from "react-router-dom"; import FilterNav from "../../components/FilterNav"; import { getProducts } from "../../api"; export function loader() { return getProducts(); } export default function Products() { const [searchParams, setSearchParams] = useSearchParams(); const [error, setError] = useState(null); const products = useLoaderData(); const uniqueCategories = [ ...new Set(products.map((product) => product.category)), ]; const uniqueBrands = [...new Set(products.map((product) => product.brand))]; const uniqueColors = [...new Set(products.map((product) => product.color))]; const uniquePrices = [...new Set(products.map((product) => product.price))]; const selectedCategory = searchParams.get("category"); const selectedBrand = searchParams.get("brand"); const selectedColor = searchParams.get("color"); function handleFilterChange(key, value) { setSearchParams((prevParams) => { let values = prevParams.get(key)?.split(","); if (values) { // existing values, add/remove specific values if (values.includes(value)) { // remove value from array values = values.filter((currentValue) => currentValue !== value); } else { // append value to array values.push(value); } if (!!values.length) { // set new key-value if values is still populated prevParams.set(key, values); } else { // delete key if values array is empty prevParams.delete(key); } } else { // no values for key, create new array with value prevParams.set(key, [value]); } if (value === null) { prevParams.delete(key); } return prevParams; }); } // function handleFilterChange(key, value) { // setSearchParams((prevParams) => { // if (value === null) { // prevParams.delete(key); // } else { // prevParams.set(key, value); // } // return prevParams; // }); // } const filteredProducts = products.filter((product) => { const filteredBrand = !selectedBrand || selectedBrand.includes(product.brand); const filteredCategory = !selectedCategory || selectedCategory.includes(product.category); const filteredColor = !selectedColor || selectedColor.includes(product.color); return filteredBrand && filteredCategory && filteredColor; }); const allProducts = filteredProducts.map((product) => ( <div key={product.id} className="product-tile"> <Link to={product.id} state={{ search: `?${searchParams.toString()}`, category: selectedCategory, }} > <h2> {product.brand} {product.name} </h2> <img src={product.image} /> <div className="product-info"> <p> {product.category} - {product.color} - ${product.price}{" "} </p> </div> </Link> </div> )); if (error) { return <h1>There was an error: {error.message}</h1>; } return ( <div className="product-list-container"> <FilterNav categoryOptions={uniqueCategories} brandOptions={uniqueBrands} colorOptions={uniqueColors} selectedCategory={selectedCategory} selectedBrand={selectedBrand} selectedColor={selectedColor} handleFilterChange={handleFilterChange} /> <div className="product-list">{allProducts}</div> </div> ); }
FilterNav组件代码
import { useState } from "react"; export default function FilterNav(props) { // const [selectedCategories, setSelectedCategories] = useState([]); // const handleCategoryClick = (category) => { // if (selectedCategories.includes(category)) { // setSelectedCategories(selectedCategories.filter((c) => c !== category)); // props.handleFilterChange("category", null); // Remove the category filter // } else { // setSelectedCategories([...selectedCategories, category]); // props.handleFilterChange("category", category); // Apply the category filter // } // }; const renderFilterList = (options, key) => { return options.map((value, id) => { return ( <a onClick={() => props.handleFilterChange(key, value)} key={id}> {value} </a> ); }); }; return ( <> <div className="product-list-filter-buttons"> <div className="dropdown"> <button className="dropbtn">Brands</button> <div className="dropdown-content"> {renderFilterList(props.brandOptions, "brand")} </div> </div> <div className="dropdown"> <button className="dropbtn">Categories</button> <div className="dropdown-content"> {renderFilterList(props.categoryOptions, "category")} </div> </div> <div className="dropdown"> <button className="dropbtn">Colors</button> <div className="dropdown-content"> {renderFilterList(props.colorOptions, "color")} </div> </div> {props.selectedCategory || props.selectedBrand || props.selectedColor ? ( <button onClick={() => { props.handleFilterChange("category", null); props.handleFilterChange("brand", null); props.handleFilterChange("color", null); }} className="product-type clear-filters" > Clear all filters </button> ) : null} </div> <div> {props.selectedCategory ? props.categoryOptions.map((category, index) => ( <button key={index} onClick={() => props.handleFilterChange("category", category)} > <span aria-hidden="true">× {category}</span> </button> )) : null} {props.selectedBrand ? ( <button onClick={() => props.handleFilterChange("brand", null)}> <span aria-hidden="true">× {props.selectedBrand}</span> </button> ) : null} {props.selectedColor ? ( <button onClick={() => props.handleFilterChange("color", null)}> <span aria-hidden="true">× {props.selectedColor}</span> </button> ) : null} </div> </> ); }
我自己感觉问题可能出在处理searchParams的逻辑,或者筛选产品时的判断条件上?比如现在获取selectedColor是用get(),是不是应该用getAll()?但之前试了没成功,也可能是我用错了方式。希望大佬们能帮忙指点一下,谢谢啦~
备注:内容来源于stack exchange,提问作者bukke
相关产品推荐
相关产品推荐

