英文:
Unable to reset the state using react-router-dom Link
问题
我有一个SearchBar
组件,其中包含一个Link
,当单击它时,会跳转到一个显示与特定类别相关的一组产品的ProductSearchScreen
。
return (
<Link to={{ pathname:#某个路径, search: `searchItem=${category.name}` }}>
{category.name}
</Link>
)
在我的ProductSearchScreen
中,我有复选框,用于筛选数据,如“类别”、“品牌”筛选等...
例如,要筛选类别,我有以下代码
const [selectedCategories, setSelectedCategories] = useState(queryParams.get('categories')?.split(',') ?? []);
<input
type="checkbox"
checked={selectedCategories.includes(category)}
onClick={() => handleCategories(category)}
/>
问题是,假设我在category1
的ProductSearchScreen
中,有一些复选框被选中,然后在搜索栏中键入category2
并导航到category2
页面,那么复选框仍然保持为checked
状态,用于category2
。
尽管在导航时我没有在queryParams
中找到任何内容,但它不会重置selectedCategories
状态。
如何确保导航到另一页时复选框不被选中?
编辑:
这是使用路径和查询字符串的组件
function ProductSearchScreen() {
const [products, setProducts] = useState([]);
const [queryParams] = useSearchParams();
// 这是我获取的查询字符串
const category = queryParams.get('searchItem');
const categories = queryParams.get('categories')?.split(',');
const uniqueCategories = getUniqueCategories(products)
// 通过axios调用,我获取产品列表并更新状态如setProducts(products)。
// 这是用于筛选类别的辅助函数
const filterCategories = (product) => {
if(categories?.length > 0) {
return categories?.includes(product.category);
} else {
return product
}
}
const filteredAndSortedProducts = products?.filter(filterCategories)
return ( <Filters uniqueCategories={uniqueCategories}/> )
}
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const [selectedCategories, setSelectedCategories] = useState(queryParams.get('categories')?.split(',') ?? []);
const handleCategories = (category) => {
if (selectedCategories.includes(category)) {
setSelectedCategories(selectedCategories.filter((c) => c !== category));
} else {
setSelectedCategories([...selectedCategories, category]);
}
}
return (
<div key={index} className="filter-type">
<input
type="checkbox"
disabled={queryParams.get('categories')?.split(',').includes(category)}
checked={selectedCategories.includes(category)}
onChange={() => handleCategories(category)}
/>
<div className="filter-item">{category}</div>
</div>
)
}
英文:
I have a SearchBar
component where I have this Link
which on click takes me to a ProductSearchScreen
which display a set of products associated with a category.
return (
<Link to={{ pathname:# somepath, search: `searchItem=${category.name}` }}>
{category.name}
</Link>
)
In my ProductSearchScreen
, I have checkboxes which filter out the data such as "category", "brand" filter etc...
For filtering out categories for example, I have this code
const [selectedCategories, setSelectedCategories] = useState(queryParams.get('categories')?.split(',') ?? []);
<input
type="checkbox"
checked={selectedCategories.includes(category)}
onClick={() => handleCategories(category)}
/>
The issue is, suppose I'm in ProductSearchScreen
of category1
and have few checkboxes clicked and in searchBar I type category2
and navigate to category2
page, the checkboxes still remain checked
for category2
.
Though I don't have anything in queryParams
on navigate, it is not resetting the state of selectedCategories
.
How can I make sure the checkboxes are not checked on navigating to another page?
Edit:
This is the component consuming the path and querystring
function ProductSearchScreen() {
const [products, setProducts] = useState([]);
const [queryParams] = useSearchParams();
// Here is the queryString i am getting
const category = queryParams.get('searchItem');
const categories = queryParams.get('categories')?.split(',');
const uniqueCategories = getUniqueCategories(products)
// with axios call, i get the list of products and update the state like setProducts(products).
// This is a helper function to filter the categories
const filterCategories = (product) => {
if(categories?.length > 0) {
return categories?.includes(product.category);
} else {
return product
}
}
const filteredAndSortedProducts = products?.filter(filterCategories)
return ( <Filters uniqueCategories={uniqueCategories}/> )
}
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const [selectedCategories, setSelectedCategories] = useState(queryParams.get('categories')?.split(',') ?? []);
const handleCategories = (category) => {
if (selectedCategories.includes(category)) {
setSelectedCategories(selectedCategories.filter((c) => c !== category));
} else {
setSelectedCategories([...selectedCategories, category]);
}
}
return (
<div key={index} className="filter-type">
<input
type="checkbox"
disabled={queryParams.get('categories')?.split(',').includes(category)}
checked={selectedCategories.includes(category)}
onChange={() => handleCategories(category)}
/>
<div className="filter-item">{category}</div>
</div>
)
}
答案1
得分: 1
Filters
组件只在挂载时检查查询参数一次。如果需要对“categories”查询参数的更改作出反应,还应该实现一个生命周期钩子,例如useEffect
,以更新selectedCategories
。
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const categories = queryParams.get('categories');
const [selectedCategories, setSelectedCategories] = useState(categories?.split(',') ?? []);
useEffect(() => {
setSelectedCategories(categories?.split(',') ?? []);
}, [categories]);
...
return (
...
);
}
请注意,当您发现自己写了一个useState
/useEffect
组合时,您可能实际上只需要useMemo
钩子。
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const categories = queryParams.get('categories');
const selectedCategories = useMemo(() => {
return categories?.split(',') ?? [];
}, [categories]);
...
return (
...
);
}
英文:
The Filters
component only checks the query params once when it mounts. If it needs to react to changes in the "categories"
query params then it should also implement a lifecycle hook, e.g. useEffect
, to update the selectedCategories
.
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const categories = queryParams.get('categories');
const [selectedCategories, setSelectedCategories] = useState(categories?.split(',') ?? []);
useEffect(() => {
setSelectedCategories(categories?.split(',') ?? []);
}, [categories]);
...
return (
...
);
}
Note that when you see that you've written a useState
/useEffect
combo that you may actually just need the useMemo
hook.
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const categories = queryParams.get('categories');
const selectedCategories = useMemo(() => {
return categories?.split(',') ?? [];
}, [categories]);
...
return (
...
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论