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

问题描述 投票:0回答:1

如果仅部分状态发生变化,是否有办法停止重新渲染?

问题是,每次我将鼠标悬停在一个标记上时,都会弹出或关闭一个弹出窗口,即使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;

javascript reactjs react-hooks react-component react-state-management
1个回答
1
投票

此行是您的问题:

key={uuidv4()}

您为什么要在每个渲染器上创建唯一的ID? ID的要点是,在渲染之间它保持不变,因此React知道它不必在DOM中重新绘制该组件。

状态改变时会发生两个阶段,渲染阶段提交阶段

渲染阶段首先发生,这是所有组件都执行其渲染功能的地方(对于功能组件,这是整个组件)。返回的JSX变成DOM节点,并添加到virtual DOM中。这非常有效,与重新渲染实际的DOM不同。

在提交阶段,将新的虚拟DOM与真实DOM进行比较,并且将重新呈现真实DOM中发现的任何差异。

React的目的是限制真实DOM的重新渲染。这不是为了限制虚拟DOM的重新计算。

这意味着当activePlace更改时,使整个组件运行其渲染周期是完全可以的。

但是,因为您要为every渲染周期中的每个country提供一个全新的ID,所以虚拟DOM认为every国家/地区已经更改(它使用ID来比较以前的DOM值) ,因此实际DOM中的所有国家/地区也会重新渲染,这可能就是为什么您看到滞后问题的原因。

ID应该是与国家/地区相关的名称,例如国家代码,而不仅仅是随机的UUID。如果您确实使用随机UUID,请将其与国家/地区保存在一起,以便始终使用相同的UUID。

© www.soinside.com 2019 - 2024. All rights reserved.