You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router页面跳转组件写法咨询及Jest+Enzyme测试建议

Answers to Your MyAccountButton Questions

Is your current useHistory implementation reasonable?

It works functionally, but it’s not the most ideal choice for pure navigation scenarios. Here’s why:

  • Semantics: Buttons are designed for triggering actions (like submitting forms or toggling UI), while links exist specifically for navigating between pages. Using a button for navigation breaks HTML’s semantic structure.
  • Accessibility: Screen readers will announce this as a "button" instead of a "link", which can confuse users relying on assistive technology. Links also come with built-in keyboard behaviors (like being focusable with Tab and navigable with Enter) that you’d have to manually add to a button.
  • Missing default behaviors: Right-clicking a button won’t give users options like "Open in new tab" or "Copy link address" unless you write custom code—features that links handle natively.

That said, if you had pre-navigation logic (like confirming a form submission or saving user data), using a button with useHistory would make perfect sense. But for your current use case (just navigating to the account page), there’s a better approach.

Absolutely! The Link component from react-router-dom is purpose-built for navigation and fixes all the issues mentioned above. Here’s how to refactor your component:

import React from 'react';
import { Link } from 'react-router-dom';
import './MyAccountButton.scss';

const MyAccountButton = ({ path }) => {
  return (
    <div className="my-account-button">
      <Link to={path} className="account-link">
        My account
      </Link>
    </div>
  );
};

export default MyAccountButton;

You can style the .account-link class in your SCSS to look like a button if needed—just make sure to keep accessibility-friendly styles (like hover/focus states) intact.

How to test with Jest and Enzyme?

Let’s cover testing both versions of the component:

Testing the original useHistory version

First, mock the useHistory hook to simulate navigation behavior:

import React from 'react';
import { shallow } from 'enzyme';
import { useHistory } from 'react-router-dom';
import MyAccountButton from './MyAccountButton';

// Mock react-router's useHistory
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useHistory: jest.fn(),
}));

describe('MyAccountButton', () => {
  it('navigates to the correct path when clicked', () => {
    const mockPush = jest.fn();
    useHistory.mockReturnValue({ push: mockPush });
    const testPath = '/user/account';

    const wrapper = shallow(<MyAccountButton path={testPath} />);
    wrapper.find('button').simulate('click');

    expect(mockPush).toHaveBeenCalledExactlyOnceWith(testPath);
  });
});

For the Link component, wrap your component in MemoryRouter to provide routing context, then verify the link’s target and navigation behavior:

import React from 'react';
import { mount } from 'enzyme';
import { Link, MemoryRouter } from 'react-router-dom';
import MyAccountButton from './MyAccountButton';

describe('MyAccountButton (Link version)', () => {
  it('renders a Link with the correct target path', () => {
    const testPath = '/user/account';
    const wrapper = mount(
      <MemoryRouter>
        <MyAccountButton path={testPath} />
      </MemoryRouter>
    );

    expect(wrapper.find(Link).prop('to')).toBe(testPath);
  });

  it('navigates to the correct path when clicked', () => {
    const testPath = '/user/account';
    const wrapper = mount(
      <MemoryRouter initialEntries={['/']}>
        <MyAccountButton path={testPath} />
      </MemoryRouter>
    );

    wrapper.find(Link).simulate('click');
    expect(wrapper.instance().history.location.pathname).toBe(testPath);
  });
});

Note: We use mount instead of shallow here because we need the full rendering context of MemoryRouter to test navigation.

内容的提问来源于stack exchange,提问作者Kopeek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 13:52:40