[英]Using useEffect to trigger a re-render by updating state, but cannot have state in dependency array?
function Map({latitude, longitude, markers}: MapProps) {
const [currentZoom, setCurrentZoom] = useState(14);
const sizeRef = useRef(null);
useEffect(() => {
const height = sizeRef.current.clientHeight;
const width = sizeRef.current.clientWidth;
const zoom = calculateZoomLevel(markers, height, width);
setCurrentZoom(zoom);
}, []);
function onMapChange({zoom}: ChangeEventValue) {
if (currentZoom !== zoom) {
setCurrentZoom(zoom);
}
}
return (
<div ref={sizeRef}>
<GoogleMapReact
defaultCenter={{
lat: latitude,
lng: longitude
}}
zoom={currentZoom}
onChange={onMapChange}
>
markers.map(function(marker) {
return (<Marker name={marker.name}/>
});
</GoogleMapReact>
</div>
);
}
I am using google-map-react
with my web app and I am trying to calculate the zoom such that all the map markers are visible on the map, the calculateZoomLevel
function uses the google-map-react
API and requires the dimensions of the map in order to calculate the required zoom level. I am using
google-map-react
with my web app and I am trying to calculate the zoom such that all the map markers are visible on the map, the calculateZoomLevel
function uses the google-map-react
API and requires the dimensions of the map为了计算所需的缩放级别。 Since I am using server-side rendering I must wait until the React component has mounted until I am able retrieve the dimensions of the map.由于我使用的是服务器端渲染,因此我必须等到 React 组件已安装,直到我能够检索 map 的尺寸。 I cannot use the
window.innerHeight/Width
property.我不能使用
window.innerHeight/Width
属性。
Therefore, in theory, I must initially render the page with a default zoom level for the map, then once it is mounted I can retrieve the component dimensions, calculate the intended zoom level and then trigger a re-render of the map.因此,理论上,我必须首先使用 map 的默认缩放级别渲染页面,然后一旦安装,我可以检索组件尺寸,计算预期的缩放级别,然后触发 map 的重新渲染。 I am using functional components along with
useEffect
in order to try and achieve this.我正在使用功能组件和
useEffect
来尝试实现这一目标。
THIS DOES NOT WORK这不起作用
const [currentZoom, setCurrentZoom] = useState(14);
useEffect(() => {
const height = sizeRef.current.clientHeight;
const width = sizeRef.current.clientWidth;
const zoom = calculateZoomLevel(markers, height, width);
setCurrentZoom(zoom);
}, []);
HOWEVER THIS DOES然而这确实
const [currentZoom, setCurrentZoom] = useState(14);
useEffect(() => {
const height = sizeRef.current.clientHeight;
const width = sizeRef.current.clientWidth;
const zoom = calculateZoomLevel(markers, height, width);
setCurrentZoom(zoom);
}, [currentZoom]);
This would be fine, however the problem is that now useEffect
is triggered every time that the zoom level is changed on the map (ie: when onMapChange
is called).这很好,但问题是现在每次在
useEffect
上更改缩放级别时都会触发 useEffect(即:调用onMapChange
时)。 When I have an empty dependency array, the useEffect
runs once after initial render, but does not properly trigger the a re-render with the updated zoom level which was just calculated.当我有一个空的依赖数组时,
useEffect
在初始渲染后运行一次,但没有正确触发使用刚刚计算的更新缩放级别的重新渲染。 It seems that I have to have the currentZoom
state inside the dependency array for the changes to propagate, but I still have to preserve the functionality of allowing the user to change the zoom on the map.似乎我必须在依赖数组中
currentZoom
state 才能传播更改,但我仍然必须保留允许用户更改 map 缩放的功能。
You should put currentZoom in Ref你应该把 currentZoom 放在 Ref
<GoogleMapReact
defaultCenter={{
lat: latitude,
lng: longitude
}}
zoom={currentZoom.current}
onChange={onMapChange}
>
Note: setState runs asynchronously, ex: currentZoom = 14 while useEffect setting the currentZoom state.注意:setState 异步运行,例如:currentZoom = 14 而 useEffect 设置 currentZoom state。 the GoogleMapReact renders but the currentZoom state is still 14 since setting state is not done yet
GoogleMapReact 渲染,但当前缩放 state 仍然是 14,因为设置 state 尚未完成
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.