如何阻止Shopify Polaris的SubNavigationItem点击时页面重载?
Shopify Polaris子导航点击页面重载问题解决方法
问题原因
SubNavigationItem的url属性会渲染原生<a>标签,点击时触发浏览器默认跳转逻辑,导致页面重载;而普通导航项你通过自定义onClick调用navigate,走的是React Router客户端路由,所以无重载问题。Polaris的SubNavigationItem不支持单独传入onClick,但可以通过Navigation组件的全局回调拦截所有导航行为。
解决方案
给Navigation组件添加onNavigationAction回调,拦截默认跳转行为,改用React Router的navigate处理路由;同时统一子导航项的路径格式,修正激活状态判断逻辑。
修改后的完整代码
import { Navigation } from '@shopify/polaris'; import './SettingsNavbar.scss'; import React, { useCallback, useEffect, useState } from 'react'; import { CreditCardMajor, CashDollarMajor, ToolsMajor, LogoBlockMajor, DiscountsMajor, CartMajor, CodeMajor, AffiliateMajor, } from '@shopify/polaris-icons'; import { useLocation, useNavigate } from 'react-router-dom'; const tabs = ["general",'subscription','dynamic-pricing', "building-blocks", "shopify-discount-codes", 'checkout-options',"assets", "integrations"]; export const SettingsNavbar: React.FC = () => { const location = useLocation(); const navigate = useNavigate(); const [activeSettingsPage, setActiveSettingsPage] = useState(''); // 拦截所有导航行为,改用React Router跳转 const handleNavigationAction = useCallback((action) => { // 阻止浏览器默认跳转 action.preventDefault(); // 获取目标路径 const targetPath = action.url; if (targetPath) { navigate(targetPath); } }, [navigate]); const handleNavItemClick = useCallback( (tabTitle: string, path?: string) => { if (path) { navigate(`/settings/${path}`); } }, [navigate] ); useEffect(()=>{ const active = tabs.find((el)=>location.pathname.includes(el)) setActiveSettingsPage(active || '') },[location.pathname]) return ( <div className='SettingsNavBar'> {/* 添加onNavigationAction回调拦截跳转 */} <Navigation location={location.pathname} onNavigationAction={handleNavigationAction}> <Navigation.Section items={[ { onClick: () => handleNavItemClick('general', 'general'), selected: activeSettingsPage === 'general', label: 'General settings', icon: ToolsMajor, }, { url: '/settings/building-blocks/sticky-bar', selected: activeSettingsPage === 'building-blocks', label: 'Building blocks', icon: LogoBlockMajor, subNavigationItems: [ { url: '/settings/building-blocks/sticky-bar', disabled: false, label: 'Sticky bar', // 子项选中状态判断:当前路径匹配该子项url selected: location.pathname === '/settings/building-blocks/sticky-bar' }, { url: '/settings/building-blocks/notification', disabled: false, label: 'Notification', selected: location.pathname === '/settings/building-blocks/notification' }, { url: '/settings/building-blocks/collection-badge', disabled: false, label: 'Collection badge', selected: location.pathname === '/settings/building-blocks/collection-badge' }, { url: '/settings/building-blocks/product-page-banner', disabled: false, label: 'Product page banner', selected: location.pathname === '/settings/building-blocks/product-page-banner' }, { url: '/settings/building-blocks/countdown-clock', disabled: false, label: 'Countdown clock', selected: location.pathname === '/settings/building-blocks/countdown-clock' }, { url: '/settings/cart-promotion-code-field', disabled: false, label: 'Cart promotion code field', selected: location.pathname === '/settings/cart-promotion-code-field' }, { url: '/settings/cart-promotion-summary', disabled: false, label: 'Cart promotion summary', selected: location.pathname === '/settings/cart-promotion-summary' }, ], }, ]} /> </Navigation> </div> ); };
关键修改点说明
- 添加全局导航拦截:通过
Navigation的onNavigationAction回调,调用action.preventDefault()阻止默认跳转,然后用navigate处理路由,实现客户端无刷新跳转。 - 统一子导航路径:修正部分子项缺失
/settings前缀的问题,确保路径与React Router配置一致。 - 子项激活状态:给每个SubNavigationItem添加
selected属性,根据当前路径精确匹配,确保选中状态正确。
内容的提问来源于stack exchange,提问作者Andriy Yurchuk
相关产品推荐
相关产品推荐

