useLocation 未检测到 MemoryRouter 的位置更改?

问题描述 投票:0回答:1

我有这个 React 组件,它依赖于 props 和要渲染的查询参数:

const Module = ({ color = 'green' }) => {
  const location = useLocation()

  let name = 'Pear'
  const matchedStr = location.search.match(/name=[a-zA-Z]+/)
  if (matchedStr){
    name = matchedStr.split('=')[1]
  }

  return <div id="Module">{`${name} is ${color}`}</div>
}

我正在尝试编写一个测试来检查组件是否对 prop 更改和查询参数更改做出反应。

/* react-testing-libray setup */

test('Module responses to both prop change and query param change', () => {
  const screen = render(
    <MemoryRouter initialEntries={["/?name=Banana"]}>
      <Module color="yellow" />
    </MemoryRouter>
  )

  expect(screen.getByText('Banana is yellow')).toBeInTheDocument() // this passes

  screen.rerender(
    <MemoryRouter initialEntries={["/?name=Apple"]}>
      <Module color="red" />
    </MemoryRouter>
   
  )

  expect(screen.getByText('Apple is red')).toBeInTheDocument() // this fails
})

我不知道如何让组件从 React-Router 钩子中观察位置变化。文本总是显示为“香蕉是红的”

部分套餐信息:

  • 反应17.0.2
  • 反应路由器-dom:6.14.2
  • 反应测试库12.1.5

我尝试过以下方法,但都不起作用:

  1. 使用
    Routes
    Route
    组件来渲染模块。
  2. 使用
    useSearhParams
    挂钩代替
    useLocation
  3. initialEntries
    MemoryRouter
    亲搞混。

只要我重新渲染当前屏幕,查询参数名称似乎就会及时冻结为“Banana”。如果我渲染一个新屏幕就好了。

javascript reactjs react-router react-router-dom react-testing-library
1个回答
0
投票

测试应实现从初始

"/?name=Banana"
URL 路径/searchParams 到下一个
"/?name=Apple"
URL 路径/searchParams 的导航更改。

使用

HistoryRouter
和自定义
history
对象,以便您可以在测试中实现导航操作。

示例:

模块.test.jsx

import { render, act } from "@testing-library/react";
import "@testing-library/jest-dom";
import { unstable_HistoryRouter as Router } from "react-router-dom";
import { createMemoryHistory } from "history"; // <-- history@5

import Module from "./Module";

const history = createMemoryHistory({
  initialEntries: ["/?name=Banana"]
});

test("Module responses to both prop change and query param change", () => {
  const screen = render(
    <Router history={history}>
      <Module color="yellow" />
    </Router>
  );

  expect(screen.getByText("Banana is yellow")).toBeInTheDocument(); // this passes

  // Navigate to new path with new search params
  act(() => {
    history.push("/?name=Apple");
  });

  screen.rerender(
    <Router history={history}>
      <Module color="red" />
    </Router>
  );

  expect(screen.getByText("Apple is red")).toBeInTheDocument(); // this fails
});

演示

Edit uselocation-not-detecting-location-change-from-memoryrouter

FWIW,您的

Module
组件以及从 URL searchParams 读取
name
值也需要改进。使用
useSearchParams
钩子来读取它们,而不是尝试对
location.search
字符串进行字符串/REGEX 处理。

示例:

import { useSearchParams } from "react-router-dom";

const Module = ({ color = "green" }) => {
  const [searchParams] = useSearchParams();
  const name = searchParams.get("name");

  return <div id="Module">{`${name} is ${color}`}</div>;
};

export default Module;
© www.soinside.com 2019 - 2024. All rights reserved.