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
相关产品推荐
相关产品推荐

