gpt4 book ai didi

javascript - React.memo 不适用于功能组件和谷歌地图

转载 作者:行者123 更新时间:2023-12-04 13:07:32 24 4
gpt4 key购买 nike

我正在尝试在 React 应用程序中插入 google maps map 。我宁愿不使用非官方图书馆(我发现那些缺乏文档的图书馆),而且我已经成功地插入了 map 。

我的问题是每次父组件的状态改变时 map 都会重新渲染;尽管更改的值与 map 的需要完全无关。

经过一些研究(我是 React 的新手),我遇到了 React.memo() HOC,它应该可以防止在 props 不变时重新渲染子组件。但是出于某种原因,我无法使其正常工作。当我在没有 Prop 的组件中插入 map 时发生的事件,父状态的任何更改都会导致重新渲染 map 。

这是父组件:

const CompanyDepotsPopup = () => {
const classes = useStyles();
const dispatch = useDispatch();
const open = useSelector((state) => selectIsDepotsPopupOpen(state));
const company = useSelector((state) => selectSelectedCompany(state));
const depotsStatus = useSelector((state) => selectDepotsStatus(state));
const {t} = useTranslation();
const [value, setValue] = useState(0);
const [phone, setPhone] = useState("");

const handleChange = (event, newValue) => {
setValue(newValue);
};

const closeModal = () => {
dispatch(toggleDepotsPopup({}));
}

useEffect(() => {
if (company) {
dispatch(depotsListed({companyId: company.id}));
}
}, [company])

if (!company) return <></>;

if (depotsStatus === "loading") {
return <CenteredLoader/>
}

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>
);
}

return (
<Dialog fullWidth={true} open={open}
aria-labelledby="company-dialog-popup">
<DialogTitle >
{company.name}
</DialogTitle>
<DialogContent style={{padding: 0, margin: 0}}>
<Divider/>
<Box mr={0} ml={0} mt={0} p={0} height="95%">
<div >
<AppBar position="static">
<Tabs value={value} onChange={handleChange} aria-label="depots tabs" centered>
<Tab label={t("Company's depots list")}/>
<Tab label={t("Add new depot")}/>
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
<DepotsList/>
</TabPanel>
<TabPanel value={value} index={1}>
<Paper>
<Grid container spacing={2}>
<Grid item xs={12} sm={12} md={12} lg={12}>
<TextField
onChange={(event) => setPhone(event.target.value)}
id="phone"
label={t("Phone")}
type="text"
fullWidth
value={phone}
/>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={12}>
<div style={{height: "250px", display: "flex", "flexDirection": "column"}}>
<MyMap
id="myMap"
/>
</div>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={12} align={"center"}>
<Button variant={"outlined"}>
{t("Save")}
</Button>
</Grid>
</Grid>
</Paper>
</TabPanel>
</div>
</Box>
</DialogContent>
<DialogActions style={{marginTop: "20px"}}>
<Button
variant={"outlined"}
onClick={closeModal}
color="secondary"
>
Done
</Button>
</DialogActions>
</Dialog>
)}

这是 map 组件:

import React, {useEffect} from "react";

const Map = ({id}) => {
const onScriptLoad = () => {
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!'
});
}

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;

每次当用户键入电话并且状态发生变化时调用 setPhone 时,都会重新渲染 map 。有人可以向我解释为什么 React.memo 不起作用以及我应该如何处理以避免重新渲染 map ?

最佳答案

我想我的直觉是这个组件

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>
);
}

这是在组件内部定义的,因此该组件的实例在任何状态更改后都会不断更改。为了防止它,把它移到组件外面,像这样

  function TabPanel()
function CompanyDepotsPopup()

代替

  function CompanyDepotsPopup() {
function TabPanel()
}

原因也是您的 TabPanel 包裹了其他一切。

关于javascript - React.memo 不适用于功能组件和谷歌地图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68696950/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com