• 浏览器是否有内存限制 前端内存溢出 前端页面占用内存 前端内存泄露


     1、 

    内存泄露发生的场景

    call setState on a component that's no longer mounted

    https://www.loginradius.com/blog/engineering/how-to-fix-memory-leaks-in-react/

    A memory leak is a commonly faced issue when developing React applications. It causes many problems, including:

    • affecting the project's performance by reducing the amount of available memory;
    • slowing down the application; and
    • crashing the system.

    So, you need to eliminate memory leaks issues.

    You may encounter the following warning message in React application when working with asynchronous calls:

    Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

    React can't detect memory leaks directly, but it introduces a warning to guide you to help figure them out on your own.

    Primary Causes Of Memory Leaks

    React components that perform state updates and run asynchronous operations can cause memory leak issues if the state is updated after the component is unmounted. Here is a normal scenario that causes this memory leak issue:

    1. The user performs an action that triggers an event handler to fetch data from an API.
    2. After that, a user clicks on a link, which navigates to another page before completing step #1.
    3. Now, the first action completes and passes the data retrieved from the API and calls function, which updates the state.

    Since the component was unmounted and function is being called in a component that is no longer mounted, it causes memory leak issue -- and in the console, you'll get a warning.

    Example of unsafe code:

    const [value, setValue] = useState('checking value...');
    useEffect(() => {
    	fetchValue().then(() => {
         setValue("done!"); // ⚠️ what if the component is no longer mounted ?
         // we got console warning of memory leak
       });
    }, []); 

    Fixes for Memory Leaks

    There are a few ways to eliminate memory leaks. Some of them are as follows.

    1) Using Boolean Flag

    const [value, setValue] = useState('checking value...');
    useEffect(() => {
    let isMounted = true;
    fetchValue().then(() => {
          if(isMounted ){
          setValue("done!"); // no more error
          } 
        });
       return () => {
        isMounted = false;
        };
    }, []);

    In the above code, I've created a boolean variable isMounted, whose initial value is true. When isMounted is true, the state is updated and function is returned. Else if the action is unmounted before completion, then function is returned with isMounted as false. This ensures that when a new effect is to be executed, the previous effect will be first taken care of.

    2) Using AbortController

    useEffect(() => {  
        let abortController = new AbortController();  
        // your async action is here  
        return () => {  
        abortController.abort();  
        }  
        }, []);

    In the above code, I've used AbortController to unsubscribe the effect. When the async action is completed, then I abort the controller and unsubscribe the effect.

    3) Using use-state-if-mounted Hook

    const [value, setValue] = useStateIfMounted('checking value...');
        useEffect(() => {
        	fetchValue().then(() => {
              setValue("done!"); // no more error
            });
        }, []);

    In the above code, I've used a hook that works just like React's useState, but it also checks that component is mounted before updating the state!

    Conclusion

    In this article, you've learned what React memory leaks are and how to use three different methods to fix memory leaks.

    https://dev.to/jeremiahjacinth13/memory-leaks-how-to-avoid-them-in-a-react-app-1g5e

    Memory Leaks, How to avoid them in a React App.

    What is a memory leak?

    According to Wikipedia, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory that is no longer needed is not released. A memory leak may also happen when an object is stored in memory but cannot be accessed by the running code.

    Simply put, a memory leak is said to occur whenever inaccessible or unreferenced data exists in memory. Nowadays, many modern programming languages have techniques for clearing out data that is no longer needed, garbage collection, but it turns out there are other not-so-popular errors which can expose your React app to memory leaks and, to a great extent, reduce the performance of your app.

    Let's look at some causes of memory leaks.

    Causes of Memory Leaks in a React Application

    memory leak.PNG

    Memory leaks in React applications are primarily a result of not cancelling subscriptions made when a component was mounted before the component gets unmounted. These subscriptions could be a DOM Event listener, a WebSocket subscription, or even a request to an API.

    The first two are not too much of a challenge, as we can easily remove an event listener or unsubscribe from the WebSocket before the component gets unmounted. But the last one might require a little bit of extra work.

    A typical React workflow

    import { useState, useEffect } from 'react';
    import { Link } from 'react-router-dom';
    import axios from 'axios';
    
    const MyCompany = function() {
        const [ company, setCompany ] = useState(null);
        useEffect(() => {
            (async () {
                 const { data } = await axios.get(
                     'https://random-data-api.com/api/company/random_company'
                 );
                 setCompany(data);
            })();
        }, []);
    
        return (
            <>
                <pre>{JSON.stringify(company, null, 3)}</pre>
                <Link to = '/anotherpage'>Another Interesting Page</Link>
            </>
        )
    }
    
     

    In the code snippet above, we have a simple component MyCompany which when mounted, makes a request to get a random company and sets value of company state to the value gotten from the API.

    The Problem

    Assuming our user has a very slow internet connection and then decides to leave the current page for another interesting page, the request would have already been made and our browser would be expecting a response, which when received, would lead us to call setState on a component that's no longer mounted.

    Aside from setting state, we would now have unimportant data in our app with no means of accessing them. This process is repeated multiple times while the user uses the app, filling up useful memory with useless and inaccessible data and leading to serious performance issues.

    We've seen the problems and I believe you understand, now let's look at how to solve this problem.

    The Way Forward: AbortControllers

    Having understood the problem, what we'd do to salvage the situation is cancel the request the moment our component unmounts, ensuring we don't get any data from the API.

    So, how do we cancel requests? AbortControllers

    According to MDN, the AbortController represents a controller object that allows you to abort one or more Web requests as and when desired. That's quite explanatory!!

    AbortControllers are created with the new AbortController() syntax, initializing an instance of the AbortController class. Every AbortController object has a read-only signal property which is passed into requests, and an abort() method which is whenever you want to cancel a request.

    Now using AbortControllers, our code should look like this:

    import { useState, useEffect } from 'react';
    import { Link } from 'react-router-dom';
    import axios from 'axios';
    
    const MyCompany = function() {
        const [ company, setCompany ] = useState(null);
    
        useEffect(() => {
             let abortController;
            (async () {
                 abortController = new AbortController();
                 let signal = abortController.signal;    
    
                 // the signal is passed into the request(s) we want to abort using this controller
                 const { data } = await axios.get(
                     'https://random-data-api.com/api/company/random_company',
                     { signal: signal }
                 );
                 setCompany(data);
            })();
    
            return () => abortController.abort();
        }, []);
    
        return (
            <>
                <pre>{JSON.stringify(company, null, 3)}</pre>
                <Link to = '/anotherpage'>Another Interesting Page</Link>
            </>
        )
    }
    
     

    Now, when our user navigates to a new page, our AbortController cancels the request and we don't have to worry about having data leaks.

    NOTE: Calling abortController.abort() after the request has been completed doesn't throw any errors. The abortController simply does not take any action on an already complete request.

    Using AbortControllers in your web apps can help improve performance and prevent memory leaks, so it's something you should actually use.

    Thanks for reading❤❤

  • 相关阅读:
    初识 MyBatis
    基于模板匹配的车牌识别
    完整java开发中JDBC连接数据库代码和步骤
    MyBatis 动态SQL
    最大子序列和问题
    二分搜索,欧几里德算法
    链表单链表
    UVA 12293 Box Game
    hdu 4565 so easy
    Bootstrap Table的使用 Cryst
  • 原文地址:https://www.cnblogs.com/rsapaper/p/16129068.html
Copyright © 2020-2023  润新知