You need to enable JavaScript to run this app. React.memo对函数组件不生效,谷歌地图随父组件无关状态变更重渲染
优惠活动
大模型
产品
解决方案
定价
更多

React.memo对函数组件不生效,谷歌地图随父组件无关状态变更重渲染

React.memo 不生效的核心原因

你遇到的问题根源不是 React.memo 失效,而是你把 TabPanel 组件定义在了 CompanyDepotsPopup 组件内部。React 组件每次状态更新重新渲染时,内部定义的函数组件都会生成全新的引用,相当于每次渲染都是不同的组件类型,React 会直接卸载旧的 TabPanel 子树,再挂载全新的子树,这种场景下 React.memo 完全不会生效,因为是整个组件的卸载重挂,不是普通的 props 变化导致的重渲染。

解决方案

1. 把 TabPanel 移到父组件外部定义

这是最核心的修复,避免每次父组件渲染都重新生成 TabPanel 实例:

// 放到 CompanyDepotsPopup 组件外部定义
function TabPanel(props) {
    const {children, value, index} = props;
    return (
        <div
            hidden={value !== index}
            style={{height: "100%"}}
        >
            {value === index && (
                <Box boxShadow={3} mt={1} ml={2} mr={2} height={"100%"}>
                    {children}
                </Box>
            )}
        </div>
    );
}

const CompanyDepotsPopup = () => {
    // 原有父组件逻辑不变,删掉内部的 TabPanel 定义即可
    const classes = useStyles();
    const dispatch = useDispatch();
    // ...其余代码保持原样
}

2. 给 Map 组件加实例缓存(可选优化)

避免特殊场景下组件重新挂载时重复初始化地图,用 useRef 存储已创建的地图实例:

import React, {useEffect, useRef} from "react";

const Map = ({id}) => {
    const mapInstanceRef = useRef(null);

    const onScriptLoad = () => {
        // 已经初始化过地图就直接跳过
        if (mapInstanceRef.current) return;
        const map = new window.google.maps.Map(
            document.getElementById(id),
            {
                center: {lat: 41.0082, lng: 28.9784},
                zoom: 8
            }
        );
        const marker = new window.google.maps.Marker({
            position: {lat: 41.0082, lng: 28.9784},
            map: map,
            title: 'Hello Istanbul!'
        });
        mapInstanceRef.current = map;
    }

    useEffect(() => {
        if (!window.google) {
            const s = document.createElement("script");
            s.type = "text/javascript";
            s.src = "https://maps.google.com/maps/api/js?key=''"
            const x = document.getElementsByTagName('script')[0];
            x.parentNode.insertBefore(s, x);
            s.addEventListener('load', e => {
                onScriptLoad();
            })
        } else {
            onScriptLoad();
        }
    }, []);

    return (
        <div style={{width: "100%", height: "100%"}} id={id}/>
    );
}

const MyMap = React.memo(Map);
export default MyMap;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 04:24:02