如果仅部分状态发生变化,是否有办法停止反应重新渲染?
问题是,每次我将鼠标悬停在一个标记上时,都会弹出或关闭一个弹出窗口,即使mystate
并没有改变,activePlace
的状态也正在改变,所有标记都会重新渲染。每当我将鼠标悬停在标记上时,console.log(myState);
就会运行。
我尝试使用useMemo钩子,但不知道如何使用它。有帮助吗?
这是我的代码:
import React, { useEffect, useState } from 'react';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
import { Icon } from 'leaflet';
const myicon = new Icon({
iconUrl: './icon.svg',
iconSize: [20, 20]
});
const MyMap = () => {
const [myState, setMyState] = useState(null);
const [activePlace, setActivePlace] = useState(null);
const getData = async () => {
let response = await axios
.get('https://corona.lmao.ninja/v2/jhucsse')
.catch(err => console.log(err));
let data = response.data;
setMyState(data);
// console.log(data);
};
useEffect(() => {
getData();
}, []);
if (myState) {
console.log(myState);
return (
<Map
style={{ height: '100vh', width: '100vw' }}
center={[14.561, 17.102]}
zoom={1}
>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>'
url={
'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png'
}
/>
{myState.map(country => {
return (
<Marker
key={uuidv4()}
position={[
country.coordinates.latitude,
country.coordinates.longitude
]}
onmouseover={() => {
setActivePlace(country);
}}
onmouseout={() => {
setActivePlace(null);
}}
icon={myicon}
/>
);
})}
{activePlace && (
<Popup
position={[
activePlace.coordinates.latitude,
activePlace.coordinates.longitude
]}
>
<div>
<h4>Country: {activePlace.country}</h4>
</div>
</Popup>
)}
</Map>
);
} else {
return <div>Loading</div>;
}
};
export default MyMap;
答案 0 :(得分:3)
此行是您的问题:
key={uuidv4()}
为什么要在每个渲染器上创建唯一的ID? ID的要点是在渲染之间它保持不变,因此React知道它不必在DOM中重新绘制该组件。
只要状态发生变化,就会发生两个阶段:渲染阶段和提交阶段。
首先进行渲染阶段,这是所有组件都执行其渲染功能的地方(对于功能组件,这是整个组件)。返回的JSX变成DOM节点,并添加到虚拟DOM 。这非常有效,并且与重新渲染实际DOM不同。
在提交阶段,将新的虚拟DOM与真实DOM进行比较,并将重新呈现真实DOM中发现的任何差异。
React的目的是限制真实DOM的重新渲染。并不是要限制虚拟DOM的重新计算。
这意味着当activePlace
更改时,使整个组件运行其渲染周期是完全可以的。
但是,由于您要在每个渲染周期中为每个country
提供一个全新的ID,因此虚拟DOM认为每个国家/地区已经更改(它使用ID来比较以前的DOM值),因此实际DOM中的所有国家/地区也会重新呈现,这可能就是为什么您看到滞后问题的原因。
ID应与国家/地区相关,例如国家代码,而不仅仅是随机的UUID。如果您确实使用随机UUID,请将其与国家/地区保存在一起,以便始终使用同一UUID。