Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

You need to pay attention to the example analysis of obsolete closures when using React/Hooks

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

Editor to share with you when using React/Hooks need to pay attention to the example analysis of obsolete closures, I believe that most people do not know much about it, so share this article for your reference, I hope you will learn a lot after reading this article, let's go to know it!

Hooks simplifies the management of the internal state and side effects of React components. In addition, duplicate logic can be extracted into a custom Hooks for reuse throughout the application.

Hooks relies heavily on JS closures. That's why Hooks is so expressive and simple, but closures can be tricky.

One of the problems you may encounter when using Hooks is outdated closures, which can be difficult to solve.

Let's start with outdated decorations. Then, take a look at how outdated closures affect React Hooks and how to solve the problem.

1. Obsolete closure

The factory function createIncrement (incBy) returns a tuple of the increment and log functions. When called, the increment () function increments the internal value by incBy, while log () prints only a message containing information about the current value:

Function createIncrement (incBy) {let value = 0; function increment () {value + = incBy; console.log (value);} const message = `Current value is ${value} `; function log () {console.log (message);} return [increment, log];} const [increment, log] = createIncrement (1); increment (); / / 1 increment (); / / 2 increment (); / / 3 / / does not work correctly! Log (); / / "Current value is 0"

[increment, log] = createIncrement (1) returns a function tuple: one function increases the internal value, and the other function records the current value.

Then, three calls to increment () increment the value to 3.

Finally, the log () call to print the message is Current value is 0, which is a bit unexpected because at this point the value is 3.

Log () is an outdated closure. The closure log () captures the message variable with the value "Current value is 0".

Even if the value variable is incremented multiple times when increment () is called, the message variable is not updated and always maintains an outdated value of "Current value is 0".

Outdated closures capture variables with out-of-date values.

two。 Fix obsolete closures

Fixing the obsolete log () problem requires closing the variable that actually changed: the closure of value.

We move the statement const message =.; to the inside of the log () function:

Function createIncrement (incBy) {let value = 0; function increment () {value + = incBy; console.log (value);} function log () {const message = `Current value is ${value} `; console.log (message);} return [increment, log];} const [increment, log] = createIncrement (1); increment (); / / 1 increment (); / / 2 increment (); / / 3 / / Works! Log (); / / "Current value is 3"

Now, after calling the increment () function three times, calling log () records the actual value: "Current value is 3".

3. Obsolete closures in Hooks

3.1 useEffect ()

Let's take a look at common cases of using useEffect () obsolete closures.

In the component, the value of count is recorded every 2 seconds in useEffect ()

Function WatchCount () {const [count, setCount] = useState (0); useEffect (function () {setInterval (function log () {console.log (`Count is: ${count} `);}, 2000);}, []); return ({count} setCount (count + 1)} > Increase);}

Open a case (https://codesandbox.io/s/stale-closure-use-effect-broken-2-gyhzk)

And click the add button several times. Then look at the console, and Count is: 0 appears every 2 seconds, although the count state variable has actually been incremented several times.

Why is this?

The first time you render, the state variable count is initialized to 0.

After the component is installed, useEffect () calls the setInterval (log, 2000) timer function, which plans to call the log () function every 2 seconds. Here, the closure log () captures that the count variable is 0.

After that, even if count increases when the Increase button is clicked, the timer function calls log () every 2 seconds, and the value of using count is still 0. Log () becomes an obsolete closure.

The solution is to let useEffect () know that the closure log () depends on count and properly handle interval resets when count changes.

Function WatchCount () {const [count, setCount] = useState (0); useEffect (function () {const id = setInterval (function log () {console.log (`Count is: ${count} `);}, 2000); return function () {clearInterval (id);}}, [count]); return ({count} setCount (count + 1)} > Increase);}

Once the dependencies are set correctly, useEffect () updates the closure as soon as the count changes.

3.2 useState ()

The component has 1 button, which increments the counter asynchronously with a delay of 1 second.

Function DelayedCount () {const [count, setCount] = useState (0); function handleClickAsync () {setTimeout (function delay () {setCount (count + 1);}, 1000);} return ({count} Increase async);}

Now open the demo (https://codesandbox.io/s/use-state-broken-0q994). Quickly click the button 2 times. The counter is only updated to 1, not the expected 2.

Each click on setTimeout (delay, 1000) will execute delay () after 1 second. The count captured by delay () at this time is 0.

Both delay () update the status to the same value: setCount (count + 1) = setCount (0 + 1) = setCount (1).

This is because the obsolete count variable 0 has been captured in the delay () closure of the second click.

To solve this problem, we use the functional method setCount (count = > count + 1) to update the count state

Function DelayedCount () {const [count, setCount] = useState (0); function handleClickAsync () {setTimeout (function delay () {setCount (count = > count + 1);}, 1000);} function handleClickSync () {setCount (count + 1);} return ({count} Increase async Increase sync);}

Open the demo (https://codesandbox.io/s/use-state-fixed-zz78r). Click the button twice again. The counter displays the correct value 2.

When a callback function that returns a new state based on the previous state is provided to the state update function, React ensures that the latest state value is provided as an argument to the callback function

SetCount (alwaysActualStateValue = > newStateValue)

This is why outdated decoration problems that occur during state updates can be solved by functions.

The above is all the content of the article "sample Analysis of obsolete closures you need to pay attention to when using React/Hooks". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report