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

标签 javascript reactjs react-hooks react-component react-state-management

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

问题是,每次我将鼠标悬停在标记上时,都会打开或关闭弹出窗口,并且它会导致所有标记重新渲染,即使 mystate 不仅仅改变 activePlace状态正在改变。每次我将鼠标悬停在标记内和外时,console.log(myState); 都会运行。

我尝试使用 useMemo Hook ,但不知道如何使用它。有什么帮助吗?

这是我的代码:

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 更改时,整个组件完全可以运行其渲染周期。

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

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

关于javascript - 如果部分状态发生变化,如何停止 react 重新渲染组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60909344/

相关文章:

javascript - 在beforeunload中添加隐藏字段

reactjs - 如何将来自 API 的响应保存到某个状态,以便我可以显示旧的搜索/响应?

reactjs - useState 和 useImmer 有什么区别?

javascript - 存储属于不同选项卡的文本区域的状态

javascript - 无法分配给 'MyComponent',因为它不是变量(ReactJS 中的 react-dnd 多拖放支持

javascript - 部署 React 时出现错误 "Path"参数必须是字符串 - 云函数中的可加载组件示例代码

javascript - react Hook : How to read & update state in hooks without infinite loops with react-hooks/exhaustive-deps rule

javascript - 检查 resize() 中窗口的宽度函数

Javascript 乘法计算器

javascript - 有没有办法覆盖 vue 组件内的转换