如何解决防止 React-Leaflet 不必要地重新渲染 Map 组件
因为我的应用在两个不同的组件中处理移动和桌面视图,所以我需要使用 useContext API 在它们之间分发状态/传播。
我有一个地图组件,当从移动设备移动到桌面设备时,地图会刷新。
根据关于 React 备忘录的 React 文档:
如果你的组件在给定相同的 props 的情况下呈现相同的结果,你 可以将其包装在对 React.memo 的调用中,以提高某些方面的性能 通过记忆结果的案例。这意味着 React 将跳过 渲染组件,并重用上次渲染的结果。
所以一开始我的想法是“为什么我不记住地图的当前 zoom
道具?”因为当遇到不同的断点(来自移动设备或桌面和 vv)时,它会导致重新渲染。
但后来我在上一段的正下方读到了这个:
React.memo 只检查 prop 的变化。如果您的功能组件 包裹在 React.memo 中的有一个 useState 或 useContext Hook 实现时,它仍然会在状态或上下文发生变化时重新渲染。
但是下面有这个!
默认情况下,它只会浅比较 props 中的复杂对象 目的。如果您想控制比较,您还可以提供 自定义比较函数作为第二个参数。
此方法仅作为性能优化存在。不要依赖 它是为了“防止”渲染,因为这会导致错误。
所以我还是尝试了一下,但首先我使用了一种地图方法来获取当前的缩放比例,然后通过 useContext 和 local-storage 保存它,这样当一个人进入移动或桌面时,至少用户会得到在地图上输入的最后一个缩放比例。
如您所见,有轻微的延迟。
这是我的实现: 地图功能:
function currentMapViewPropsAreEqual(prevProps,nextProps) {
return (
prevProps.currentMapView === nextProps.currentMapView &&
prevProps.Map === nextProps.Map &&
prevProps.TileLayer === nextProps.TileLayer
);
}
function MyMap({ currentMapView,Map,TileLayer }) {
var [animate,setAnimate] = useState(false);
var [userLocation,setUserLocation] = useState(null);
var handleWaypointsOnMapRef = useRef(handleWaypointsOnMap);
var mapRef = useRef();
var mapRefForRoutingMachine = useRef();
var { state } = userState();
var { dispatch } = userDispatch();
var {
currentMap,isRoutingVisible,removeRoutingMachine,isLengthOfMarkersLessThanTwo,markers
} = state;
useEffect(() => {
handleWaypointsOnMapRef.current = handleWaypointsOnMap;
}); // update after each render
function handleOnViewportChanged(e) {
var { current = {} } = mapRef;
var { leafletElement: map } = current;
map.on('zoomend',function() {
var zoom = map.getZoom();
dispatch({
type: 'setMapZoom',payload: {
currentMapView: zoom
}
});
});
}
function handleOnLocationFound(e) {
var { current = {} } = mapRef;
var { leafletElement: map } = current;
map.setZoom(currentMapView);
var latlng = e.latlng;
var radius = e.accuracy;
var circle = L.circle(latlng,radius);
circle.addTo(map);
}
return (
<Map
preferCanvas={true}
id="myMap"
animate={animate}
zoom={currentMapView}
ref={mapRef}
onViewportChanged={handleOnViewportChanged}
onClick={e => handleWaypointsOnMap(e)}
>
<TileLayer
url={`https://api.mapbox.com/styles/v1/${process.env.MAPBOX_USERNAME}/${
process.env.MAPBOX_STYLE_ID
}/tiles/256/{z}/{x}/{y}@2x?access_token=${process.env.MAPBOX_ACCESS_TOKEN}`}
attribution='Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors,<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>,Imagery © <a href="https://www.mapbox.com/">Mapbox</a>'
/>
{mapRef && (
<Routing
isRoutingVisible={isRoutingVisible}
ref={mapRefForRoutingMachine}
markers={markers}
stringify={stringify}
isLengthOfMarkersLessThanTwo={isLengthOfMarkersLessThanTwo}
removeRoutingMachine={removeRoutingMachine}
userLocation={userLocation}
/>
)}
</Map>
);
}
var MemoizedMyMap = React.memo(MyMap,currentMapViewPropsAreEqual);
这是仪表板,因此您可以看到我将实际的 Map
作为带有 zoom
属性的道具传递:
import { Map,TileLayer } from 'react-leaflet';
import { userState,userDispatch } from '../components/Context/UserContext.jsx';
const MyMap = dynamic(() => import('../components/Map/MyMap.jsx'),{
ssr: false
});
var Dashboard = ({ props }) => {
var { state } = userState();
var { dispatch } = userDispatch();
var { currentMapView } = state;
return (
<>
<MyMap Map={Map} TileLayer={TileLayer} currentMapView={currentMapView} />
</>
);
};
那么有没有人知道如何在移动和桌面之间遍历断点时保持地图道具/状态完整无缺。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。