useLocation无法检测MemoryRouter路由变化?测试问题求助
问题原因
当你使用screen.rerender重新渲染MemoryRouter时,尽管传入了新的initialEntries,但MemoryRouter在初始化时创建的history实例不会随props变化而重置。这导致路由上下文始终保持第一次渲染时的状态(/?name=Banana),所以useLocation或useSearchParams获取到的还是旧的查询参数,最终组件显示Banana is red。
解决方案
方案1:手动控制history实例
通过createMemoryHistory创建可手动操作的history对象,直接更新路由状态,再配合重新渲染更新组件props:
import { render, screen } from '@testing-library/react'; import { Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import Module from './Module'; test('Module responses to both prop change and query param change', () => { // 初始化history实例 const history = createMemoryHistory({ initialEntries: ["/?name=Banana"] }); render( <Router location={history.location} navigator={history}> <Module color="yellow" /> </Router> ); expect(screen.getByText('Banana is yellow')).toBeInTheDocument(); // 更新路由查询参数 history.replace("/?name=Apple"); // 重新渲染组件并更新props render( <Router location={history.location} navigator={history}> <Module color="red" /> </Router> ); expect(screen.getByText('Apple is red')).toBeInTheDocument(); });
方案2:卸载后重新渲染
如果坚持使用MemoryRouter,可以先卸载原有组件,再重新渲染新的MemoryRouter实例:
import { render, screen, unmountComponentAtNode } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import Module from './Module'; test('Module responses to both prop change and query param change', () => { const container = document.createElement('div'); document.body.appendChild(container); // 第一次渲染 render( <MemoryRouter initialEntries={["/?name=Banana"]}> <Module color="yellow" /> </MemoryRouter>, { container } ); expect(screen.getByText('Banana is yellow')).toBeInTheDocument(); // 卸载组件 unmountComponentAtNode(container); // 重新渲染新的路由和组件 render( <MemoryRouter initialEntries={["/?name=Apple"]}> <Module color="red" /> </MemoryRouter>, { container } ); expect(screen.getByText('Apple is red')).toBeInTheDocument(); // 清理 document.body.removeChild(container); });
为什么之前的尝试无效
- 使用
Routes和Route:问题核心是MemoryRouter的history状态未更新,和路由嵌套结构无关,因此添加Routes无法解决。 - 替换为
useSearchParams:useSearchParams同样依赖路由上下文的history状态,只要history未更新,就无法获取新参数。 - 修改
initialEntries:MemoryRouter的initialEntries仅在组件初始化时生效,后续props变化不会重置已创建的history实例状态。
内容的提问来源于stack exchange,提问作者chulinguy
相关产品推荐
相关产品推荐

