如何解决React Hook的关闭问题? [英] How To Solve The React Hook Closure Issue?

查看:116
本文介绍了如何解决React Hook的关闭问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 从"react"导入React,{useState};从"react-dom"导入ReactDOM;函数App(){const [count,setCount] = useState(0);函数handleAlertClick(){return(setTimeout(()=> {警报(您点击了:" +计数);},3000))}返回 (< div>< p>您点击了{count}次</p>< button onClick = {()=>setCount(count + 1)}>点击我</button>< button onClick = {handleAlertClick}>显示警报</button></div>);} 

我只想知道这是否能按我认为的方式工作,或者是否有更好的解释!

每当调用 setState 方法时,状态就会获得新的引用.这意味着原始状态没有新值,但是我们改为创建具有新值的新状态.当我们单击第二个按钮时,事件处理程序功能将捕获原始状态的引用.即使我们多次单击第一个按钮,当警报显示时,它也会显示事件处理程序捕获其引用的状态的值.

这正确吗?

解决方案

警报显示 count 过时的值的原因是因为回调传递给了setTimeout 引用的是闭包捕获的 count 的过时值.这通常称为失效关闭.

在初始渲染时,作为回调传递给 setTimeout 的匿名函数将 count 的值捕获为 0 ,并在按下按钮时点击 show alert 会使回调进入队列,但计数值已过时.

在上述情况下,最简单的解决方案是使用 ref 在警报消息中显示计数的更新值并解决陈旧性关闭问题.

  function App(){const [count,setCount] = useState(0);const LatestValue = useRef(count);const handleAlertClick =()=>{setTimeout(()=> {alert(`count is:$ {latestValue.current}`);},3000);};返回 (< div>< p>您点击了{count}次</p><按钮onClick = {()=>{setCount(prev => {LatestValue.current = prev + 1;返回prev + 1;});}}>点击我</button>< button onClick = {handleAlertClick}>显示警报</button></div>);} 

codesandbox

挂钩在很大程度上依赖于关闭,因此很可能会遇到有关陈旧关闭的问题.这是一个很好的文章,内容涉及在使用react-hooks和演示了如何在某些情况下解决某些问题.


import React, { useState} from "react";
import ReactDOM from "react-dom";

function App() {
  const [count, setCount] = useState(0);

  function handleAlertClick(){
    return (setTimeout(() => {
  alert("You clicked on: " + count);
}, 3000))
  }


  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <button onClick={handleAlertClick}>Show alert</button>
    </div>
  );
}

I just want to know if this works the way that I think it does, or if there is a better explanation!

Whenever the setState method is called the state gets a new reference. This means the original state doesn't have a new value, but we instead create a new state with a new value. When we click on the second button, the event handler function captures the reference of the original state. Even if we click the first button many times, when the alert is displayed it will show the value of the state that the event handler captured its reference.

Is this correct?

解决方案

The reason the alert shows the outdated value of count is because the callback passed to setTimeout is referencing an outdated value of count captured by the closure. This is usually referred to as a stale-closure.

On the initial render, the anonymous function passed as a callback to setTimeout captures the value of count as 0, and when the button show alert gets clicked the callback gets queued but with the outdated value of count.

In the case above the easiest solution to show the updated value of count in the alert message and fix the stale-closure issue will be to use a ref.

function App() {
  const [count, setCount] = useState(0);

  const latestValue = useRef(count);

  const handleAlertClick = () => {
    setTimeout(() => {
      alert(`count is: ${latestValue.current}`);
    }, 3000);
  };

  return (
    <div>
      <p>You clicked {count} times</p>
      <button
        onClick={() => {
          setCount(prev => {
            latestValue.current = prev + 1;
            return prev + 1;
          });
        }}
      >
        Click me
      </button>
      <button onClick={handleAlertClick}>Show alert</button>
    </div>
  );
}

Working demo in codesandbox

Hooks rely heavily on closures to work, so it very likely that you may bump into problems regarding stale-closures. Here is a nice article on how stale-closures create issues when using react-hooks and demonstrates how to fix some the issue in some situations.

这篇关于如何解决React Hook的关闭问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆