
在 React 应用中,使用 react-router-dom 提供的 Link 组件进行页面跳转非常常见。然而,在某些场景下,我们可能会遇到一个问题:当从一个页面导航到另一个页面时,组件的状态没有正确重置,导致出现意料之外的行为。例如,在一个产品搜索页面,用户选择了一些筛选条件(比如复选框),然后通过 Link 组件导航到另一个分类的搜索页面,之前选中的筛选条件仍然处于选中状态。这显然不是我们期望的结果。
这个问题通常是由于组件的状态只在组件首次挂载时初始化一次,之后即使 URL 发生了变化,状态也不会自动更新。为了解决这个问题,我们需要使用 useEffect 或 useMemo Hook,以便在每次 URL 参数发生变化时,强制更新组件的状态。
使用 useEffect Hook
useEffect Hook 允许我们在组件渲染后执行副作用操作。我们可以利用它来监听 URL 参数的变化,并在参数变化时更新组件的状态。
假设我们有一个 Filters 组件,它根据 URL 中的 categories 参数来控制复选框的选中状态:
import { useState, useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const categories = queryParams.get('categories');
const [selectedCategories, setSelectedCategories] = useState(categories?.split(',') ?? []);
useEffect(() => {
setSelectedCategories(categories?.split(',') ?? []);
}, [categories]);
const handleCategories = (category) => {
if (selectedCategories.includes(category)) {
setSelectedCategories(selectedCategories.filter((c) => c !== category));
} else {
setSelectedCategories([...selectedCategories, category]);
}
}
return (
{uniqueCategories.map((category, index) => (
handleCategories(category)}
/>
{category}
))}
);
}
export default Filters;在这个例子中,useEffect Hook 监听 categories 变量的变化。每当 categories 发生变化(例如,用户通过 Link 组件导航到不同的页面),useEffect 就会重新执行,并使用新的 categories 值来更新 selectedCategories 状态。这样就确保了复选框的选中状态始终与 URL 参数保持同步。
使用 useMemo Hook
useMemo Hook 允许我们缓存计算结果,只有当依赖项发生变化时才重新计算。在这种情况下,我们可以使用 useMemo 来计算 selectedCategories 的初始值,并在 categories 发生变化时重新计算。
import { useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
function Filters({ uniqueCategories }) {
const [queryParams, setQueryParams] = useSearchParams();
const categories = queryParams.get('categories');
const selectedCategories = useMemo(() => {
return categories?.split(',') ?? [];
}, [categories]);
// ... 其他代码
}在这个例子中,useMemo Hook 监听 categories 变量的变化。每当 categories 发生变化,useMemo 就会重新计算 selectedCategories 的值,并返回新的值。由于 selectedCategories 是一个常量,它会自动触发组件的重新渲染,从而更新复选框的选中状态。
选择 useEffect 还是 useMemo?
通常,如果状态的更新涉及到副作用操作(例如,发送网络请求),则应该使用 useEffect Hook。如果状态的更新仅仅是根据现有数据进行计算,则可以使用 useMemo Hook。
在这个例子中,selectedCategories 的更新仅仅是根据 categories 进行计算,因此使用 useMemo 更加简洁和高效。
注意事项
- 确保将 URL 参数作为 useEffect 或 useMemo 的依赖项,以便在参数变化时触发状态更新。
- 避免在 useEffect 或 useMemo 中进行不必要的计算,以提高性能。
- 如果状态的更新涉及到多个 URL 参数,可以将这些参数都作为依赖项。
总结
通过使用 useEffect 或 useMemo Hook,我们可以有效地解决在使用 React Router Dom 的 Link 组件进行页面跳转时,组件状态未能正确重置的问题。这两种方法都可以确保组件在每次导航时根据新的 URL 参数更新状态,从而避免出现状态残留的情况。根据实际情况选择合适的方法,可以使我们的代码更加简洁、高效和易于维护。










