带Props的React组件中使用react-router-dom Link报错求助
问题分析与修复方案
核心问题:测试时缺少Router上下文
Link组件依赖react-router提供的上下文(由BrowserRouter/HashRouter等容器组件创建)才能正常工作。你在测试中直接渲染Item组件,没有用BrowserRouter包裹,导致上下文为null,触发了Cannot destructure property 'basename'...的错误。
额外问题1:Item组件的Props解构错误
你的Item组件参数写成了({info},{addCart}),这是错误的——函数组件的props是单个对象,应该改成({info, addCart}),否则addCart会被解析为undefined,点击按钮时会触发调用错误。
额外问题2:测试用例的调用逻辑错误
第二个测试里,你渲染组件时传了addCart={addCartMock(details)},这会直接执行mock函数并传入参数,正确的做法是传递mock函数本身addCart={addCartMock},点击按钮后再验证调用情况。
修改后的代码
item.js
import { Link } from "react-router-dom"; // 修正props解构方式 const Item = ({ info, addCart }) => { return ( <> <Link to="/"><button>X</button></Link> <img src={info.pic} alt={info.title} /> <h1>{info.title}</h1> <p>{info.description}</p> <button onClick={() => addCart(info)}>Add</button> </> ); }; export default Item;
item.test.js
import React from 'react'; import { render, cleanup, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; import userEvent from '@testing-library/user-event'; import Item from './item'; // 导入BrowserRouter用于提供上下文 import { BrowserRouter } from 'react-router-dom'; afterEach(cleanup); const details = { pic: `a pic`, title: `a title`, description: `a description` }; const addCartMock = jest.fn(); // 封装带Router的渲染函数,避免重复代码 const renderWithRouter = (component) => { return render(<BrowserRouter>{component}</BrowserRouter>); }; test(`Content renders`, () => { // 使用封装的renderWithRouter渲染组件 renderWithRouter(<Item info={details} addCart={addCartMock} />); const image = screen.getByAltText(`${details.title}`); expect(image).toBeInTheDocument(); expect(image).toHaveAttribute(`src`, `${details.pic}`); expect(screen.getByRole(`heading`, { name: details.title })).toBeInTheDocument(); expect(screen.getByText(`${details.description}`)).toBeInTheDocument(); expect(screen.getByRole(`button`, { name: `Add` })).toBeInTheDocument(); expect(screen.getByRole(`button`, { name: `X` })).toBeInTheDocument(); }); test(`Add button click event`, () => { renderWithRouter(<Item info={details} addCart={addCartMock} />); userEvent.click(screen.getByRole(`button`, { name: `Add` })); expect(addCartMock).toHaveBeenCalledWith(details); });
内容的提问来源于stack exchange,提问作者wavesinaroom
相关产品推荐
相关产品推荐

