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

React-router-Dom useNavigate引发地图应用卡片重复渲染问题求助

解决地图移动时侧边栏卡片重复渲染的问题

你的问题核心在于地图移动触发URL搜索参数变化,进而导致组件树重渲染,侧边栏的Card组件也跟着不必要地重复渲染。结合你的代码,我整理了几个针对性的优化方案:

1. 用React.memo包裹Card组件

React.memo会对组件的props做浅比较,只有当props真正发生变化时才会重新渲染组件。你的Card组件接收的title、img、color等props在地图移动时并没有变化,所以这是最直接的优化手段。

修改你的Card.js:

import { memo } from 'react'; // 引入memo
import useNavigateSearch from "../../../hooks/useNavigateSearch";

const Card = ({title, img, color, route, id}) => {
    const navigate = useNavigateSearch();
    console.log('render')

    const handleClick = (route, id) => {
        navigate(`${route}/${id}`, {map: '2d'})
    }
    return (
        <div className="w-24 h-20 mt-1 flex flex-col justify-center items-center cursor-pointer"
             onClick={()=> handleClick(route, id)}>
                <div className={`w-12 h-12 ${color} rounded-full flex justify-center items-center`}>
                    <img src={img} className="w-8 h-8 brightness-0 invert"/>
                </div>
                <div className="text-sm">
                    {title}
                </div>
        </div>
    )
}

export default memo(Card); // 用memo包裹后导出

2. 优化useNavigateSearch的返回函数,保持引用稳定

当前你的useNavigateSearch每次调用都会返回一个新的箭头函数,这会导致Card组件每次渲染时拿到的navigate都是新引用。我们可以用useCallback让这个函数引用稳定下来:

修改useNavigateSearch.js:

import {createSearchParams, useNavigate} from "react-router-dom";
import { useCallback } from 'react'; // 引入useCallback

const useNavigateSearch = () => {
  const navigate = useNavigate();
  // 用useCallback包裹,确保函数引用稳定
  return useCallback((pathname, params) => {
    navigate({ pathname, search: `?${createSearchParams(params)}` });
  }, [navigate]); // 依赖仅为稳定的navigate函数
};

export default useNavigateSearch;

3. 用useCallback包裹Card中的handleClick函数

为了彻底避免因函数引用变化导致的潜在重渲染,我们可以用useCallback包裹Card里的点击事件处理函数:

修改Card.js中的handleClick部分:

import { memo, useCallback } from 'react';
import useNavigateSearch from "../../../hooks/useNavigateSearch";

const Card = ({title, img, color, route, id}) => {
    const navigate = useNavigateSearch();
    console.log('render')

    // 用useCallback包裹,依赖为稳定的navigate、route、id
    const handleClick = useCallback(() => {
        navigate(`${route}/${id}`, {map: '2d'})
    }, [navigate, route, id]);

    return (
        <div className="w-24 h-20 mt-1 flex flex-col justify-center items-center cursor-pointer"
             onClick={handleClick}> {/* 直接绑定函数,避免创建新箭头函数 */}
                <div className={`w-12 h-12 ${color} rounded-full flex justify-center items-center`}>
                    <img src={img} className="w-8 h-8 brightness-0 invert"/>
                </div>
                <div className="text-sm">
                    {title}
                </div>
        </div>
    )
}

export default memo(Card);

完成以上修改后,只有当Card的props(route、id等)或稳定化后的navigate函数发生变化时,组件才会重新渲染,地图移动时的URL参数变化就不会再触发不必要的渲染了。

额外检查点

  • 确保父组件传递给Card的img、color等props不是每次渲染都生成新引用(比如动态生成的对象),如果是这种情况,需要用useMemo对这些props做稳定化处理。
  • 确认Redux状态更新时,没有意外更新侧边栏相关的状态(根据你的描述,侧边栏状态由URL控制,这部分应该没问题)。

内容的提问来源于stack exchange,提问作者Selahattin ŞİŞMAN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:15:57