Stopping React from re-rendering a component when only a specific part of the state changes

Is there a way to prevent unnecessary re-renders in React when only part of the state changes?

The issue I'm facing is that whenever I hover over a marker, a popup opens or closes, causing all markers to re-render even though 'myState' remains unchanged and only the 'activePlace' state is updated. The 'console.log(myState);' statement runs every time I hover in and out of a marker.

I attempted to utilize the useMemo hook but couldn't quite figure out how to implement it. Any guidance on this matter would be greatly appreciated.

Below is my code snippet:

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;

Answer №1

Your problem lies in this line:

key={uuidv4()}

Do you really need to create a unique ID every time the component renders? The purpose of an ID is to remain unchanged between renders so that React can optimize and avoid redrawing that specific component in the DOM.

When state changes, there are two main phases involved: the render phase and the commit phase.

The render phase comes first, where all components execute their render functions (in the case of function components). The JSX returned is converted into virtual DOM nodes before being added to the actual DOM. This process is efficient and doesn't equate to re-rendering the entire DOM.

In the commit phase, the new virtual DOM is compared against the real DOM, and any discrepancies found in the real DOM will trigger re-renders.

The goal of React is to minimize unnecessary re-renders of the real DOM, not to prevent the recalculation of the virtual DOM.

It's perfectly fine for the whole component to go through its render cycle when activePlace changes.

However, assigning a new ID to each country during every render causes the virtual DOM to register changes for every country (it uses IDs for comparison), leading to all countries in the actual DOM getting re-rendered. This could be the reason behind the lag issues you're experiencing. The ID should be something related to the country, like a country code, instead of just a random UUID. If using UUIDs, make sure to associate them with the country to ensure consistency.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Building a MERN-stack application with user authentication using react-router, all without the need

I am currently in the process of implementing authentication for my application, but I have a specific question. I have set up basic authentication on the backend, generating a token that is then sent to the frontend and stored in a cookie. I have learned ...

Having difficulty rendering JSON data on an HTML webpage

Currently, I am working on an API App that utilizes the Foursquare API. With the help of my getRequest function, I am able to obtain results in JSON format, which are then displayed in my console.log. However, the challenge lies in parsing the data from J ...

What is the best way to send a JSON object array result to my API endpoint in React?

I am currently working on fetching data from 2 different APIs from the backend. The challenge I am facing is that the JSON result I receive from the first API is in the form of an object array in JSON format. My goal is to pass the ID from the first API ...

What is the best way to conduct tests on React components' methods and ensure they are integrated into my Istanbul coverage report

Is there a way to test the methods of react components and include them in my Istanbul test coverage? Edit: I'm using enzyme. Just wanted to mention that. Take, for instance, this component: class SearchFormContainer extends Component { static h ...

The Fetch API within DatoCMS isn't able to retrieve all published posts

I am trying to retrieve all of my published blog posts from DatoCMS. Currently, I have implemented the code below. The issue I am facing is that it only retrieves 65 posts when I know I have more than 100... Can anyone help me figure out what I might be d ...

Here's how you can arrange a list starting with the first item and then searching for a specific string using md-autocomplete in

As a newcomer to angularJs, I am looking for ways to filter search results more efficiently. Check out this example here: https://codepen.io/anon/pen/mpJyKm I am trying to customize the search result by filtering based on query input. Specifically, I wan ...

Connecting to a pathway of Material-UI menu items

I am currently utilizing Material-UI's menu components as part of my project requirements. However, I am encountering difficulties in properly routing each MenuItem to an existing route within my application. As a temporary solution, I have resorted ...

Tips on adding several elements to an array depending on the selected value from various checkboxes?

I am working on a project where I need to populate an array based on selected checkboxes. Let's assume we have 3 arrays containing strings: const fruits = ["Apple", "Banana", "Orange", "Grapes"]; const vegetable ...

What is the best way to verify and eliminate unnecessary attributes from a JSON request payload in a node.js application?

My goal is to verify the data in the request payload and eliminate any unknown attributes. Example of a request payload: { "firstname":"john", "lastname":"clinton", "age": 32 } Required attributes: firstname and lastname Optional a ...

Tips for incorporating Angular2 into Eclipse using TypeScript

Recently, I delved into the world of Angular 2 and noticed that TypeScript is highly recommended over JavaScript. Intrigued by this recommendation, I decided to make the switch as well. I came across a helpful guide for setting up everything in Eclipse - f ...

Angular - Ensuring service completion before proceeding with navigation

I'm currently facing an issue where I need to populate data in a service before navigating, but the navigation is happening before the data is ready. Here's the code in my service: addToken(token) { this.cookieService.set( 'token', ...

Guide on adding a timestamp in an express js application

I attempted to add timestamps to all my requests by using morgan. Here is how I included it: if (process.env.NODE_ENV === 'development') { // Enable logger (morgan) app.use(morgan('common')); } After implementing this, the o ...

How can I replicate the functionality of a div mimicking a select element using javascript upon clicking away from the element?

My task was to design a pseudo-select element that showcases columns for each row within the select. Due to HTML's restriction on allowing the <option> tag to include HTML, I had to find an alternate solution. One issue I encountered was replic ...

Error message in vuejs: JSON parsing error detected due to an unexpected "<" symbol at the beginning

I have been trying to troubleshoot this issue, but I am having trouble understanding how to resolve it. Currently, I am using lottie-web in a project and need to set the animation parameters on an object in order to pass them as a parameter later. This i ...

When attempting to send emails, SendGrid encounters an error and fails to provide an error code

Earlier today, I successfully sent out a series of emails using SendGrid. It was quite a large number of emails, as I needed to create multiple user accounts with attached email addresses. Thankfully, everything went smoothly and all the emails were delive ...

What is the best way to locate the final text node within the <p> element?

Looking at the code below, my goal is to identify and retrieve the text node that serves as the last child element. <p class="western" style="margin-bottom: 0.14in"> <font color="#000000"> <font face="Arial, serif"> <font ...

Modify a section of an HTML text's formatting

function changeEveryCharColor(id) { var part; var whole = ""; var cool1 = document.getElementById(id).innerHTML; console.log(cool1); for(var i = 0; i < cool1.length; i++) { color1 = getRandomInt(255); ...

Efficient methods to reach the desired result using Selenium WebDriver promises

After working on a piece of code that utilizes Selenium WebDriver to retrieve the text of an element, I am wondering if there is a more concise way to accomplish this task? async function getText(driver, locator) { return await (await driver.findEleme ...

Automated Menu Selection using Selenium

I'm currently facing a challenge in writing a Python script using Selenium to interact with a webpage. I am struggling to use the .click() method to select an expandable list on the page. Despite successfully logging in and navigating to the desired p ...

Guide to sending API requests from a React client to an Express server hosted on Heroku

I've been grappling with deploying a Twitch-like application using a combination of react, redux, node media server, and json server module to Heroku. One roadblock I keep hitting is when attempting to establish a connection between my react client an ...