如果部分状态发生变化,如何停止重新渲染组件?

How to stop react re-rendering component, if part of the state changes?

如果只有部分状态发生变化,有没有办法停止 React 重新渲染?

问题是,每次我将鼠标悬停在标记上时,都会打开或关闭弹出窗口,这会导致所有标记重新呈现,即使 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='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <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;

这一行是你的问题:

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。