I Love ReactJS

UseEffect executes twice in React18

this article is used to record some of the author's gains in the section strict mode in the official React18 documentation, concerning the role of strict mode, why React executes useEffect twice, and how to optimize it.

strict mode (Strict Mode)

what is strict mode

strict mode is a tool to check for possible problems in your application. Strict mode only runs in a development environment, but it has no impact in a production environment.

import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>      <Footer />
    </div>
  );
}

you can use React.StrictMode to wrap the apps you want to check. Apps without packages will not be affected. For example, the & lt;Header / & gt; component in the above code will not be affected by the strict mode, only the & lt;ComponentOne / & gt; and & lt;ComponentTwo> that we package will be affected by the strict mode.

the role of strict mode

strict mode makes the following checks

ReactThe official document of React provides an example, which should mean that if we jump from Route A to Route B and then return from Route B.
ReactI hope to immediately display the original state, so that I can cache the state of A, so that when we return, we can immediately render it based on the state in the cache.

Why does React set useEffect to execute twice

We just mentioned that React will support remounting to the tree using the state of the components that existed before the uninstall. However, components are required to be resilient to the side effects of multiple mounts and destruction. Here we need to have a good understanding of the side effects of React, and the author has not fully understood the meaning of this sentence, but we can understand the usage scenario of useEffect according to the examples given in the official React documentation, and then come back to understand the meaning of this sentence.

seems to mean that if React does not set Effect to execute twice, then React may cause some problems when doing this optimization. And these problems will not be noticed by developers, so React set Effect to execute twice in order to expose the problem in advance. React also believes that Effect execution twice is no problem in most cases

non-strict mode

* React mounts the component. //Mount components
  * Layout effects are created. //Layout Execution
  * Effects are created. //Effects Execution

strict mode

* React mounts the component. //Mount components
    * Layout effects are created. //layout Execution
    * Effect effects are created. // Effects Execution
* React simulates effects being destroyed on a mounted component. //React simulation component destruction
    * Layout effects are destroyed. // Layout Destroy
    * Effects are destroyed.       // Effects Destroy
* React simulates effects being re-created on a mounted component. // React simulates remounting
    * Layout effects are created  // Layout Recreate
    * Effect setup code runs     //  Effect re execution

how to deal with the problem of Effect execution twice in the application

React believes that executing twice doesn't make a difference in most cases, and we should consider how to get Effect to execute correctly after remounting, rather than how to get Effect to execute once. Let's take a look at some optimized scenarios.

request data

We can use a variable to control that the request is sent only once, or we can improve it by canceling the request.

useEffect(() => {  
    let ignore = false;  
    async function startFetching() {  
        const json = await fetchTodos(userId);  
        if (!ignore) { 
            setTodos(json);  
        }  
}  

    startFetching();  
    return () => {  
       ignore = true;  
    };  
}, [userId]);

pop-up window problem

remove the pop-up window close before the second mount, and there will be no problem of calling showModal () twice

useEffect(() => {  
    const dialog = dialogRef.current;  
    dialog.showModal();  
    return () => dialog.close();  
}, []);

Not an Effect: Buying a product

I don't know how to translate the title. Just bring it over and use it

.

useEffect(() => {  
    fetch('/api/buy', { method: 'POST' });  
}, []);

React believes that it is incorrect to send a post request in useEffect, and this requirement scenario does not exist. You should send a post request in a click event, not directly in the useEffect.

setTimeout

remember to cancel the timer in useEffect

  useEffect(() => {
    function onTimeout() {
      console.log('⏰ ' + text);
    }

    console.log('⏰  Schedule "' + text + '" log');
    const timeoutId = setTimeout(onTimeout, 3000);

    return () => {
      console.log('⏰  Cancel "' + text + '" log');
      clearTimeout(timeoutId);
    };
  }, [text]);
Exit mobile version