React Hooks 如何使用Callback“冻结"?关闭? [英] How does React Hooks useCallback "freezes" the closure?

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

问题描述

我想知道 React 如何在使用 useCallback 钩子(以及其他钩子)时冻结"闭包,然后仅在传递它们时更新钩子内使用的变量进入 inputs 参数.

I'd like to know how does React "freezes" the closure while using the useCallback hook (and with others as well), and then only updates variables used inside the hook when you pass them into the inputs parameter.

我知道冻结"可能不是很清楚,所以我创建了一个 REPL.it 来显示我的意思:https://repl.it/repls/RudeMintcreamShoutcast.打开代码后,打开 Web 浏览器控制台并开始单击 count 按钮.

I understand that the "freeze" may not be very clear, so I created a REPL.it that shows what I mean: https://repl.it/repls/RudeMintcreamShoutcast. Once you open the code, open your web browser console and start clicking on the count button.

如果外部的值与内部的值相比,对于相同的变量,如果它们在相同的闭包下并引用相同的事物,那么它们如何不同?我不熟悉 React 代码库,所以我想我在这里遗漏了一个幕后实现细节,但我试图思考它是如何工作的几分钟,但无法很好地理解 React 是如何工作的实现这一目标.

How come the value outside compared to the one inside, for the same variable, is different, if they're under the same closure and referencing the same thing? I'm not familiar with React codebase and so I suppose I'm missing an under the hood implementation detail here, but I tried to think how that could work for several minutes but couldn't come up with a good understanding on how React is achieving that.

推荐答案

第一次渲染组件时,useCallback 钩子会将传递的函数作为它的参数并将其存储在场景.当您调用回调时,它会调用您的函数.到目前为止,一切都很好.

The first time the component is rendered, the useCallback hook will take the function that is passed as its argument and stores it behind the scenes. When you call the callback, it will call your function. So far, so good.

第二次渲染组件时,useCallback 钩子会检查你传入的依赖.如果它们没有改变,你传入的函数被完全忽略!当您调用回调时,它将调用您在第一次渲染时传入的函数,该函数仍然引用该时间点的相同值.这与您作为依赖项传入的值无关 - 这只是普通的 JavaScript 闭包!

The second time that the component is rendered, the useCallback hook will check the dependencies you passed in. If they have not changed, the function you pass in is totally ignored! When you call the callback, it will call the function you passed in on the first render, which still references the same values from that point in time. This has nothing to do with the values you passed in as dependencies - it's just normal JavaScript closures!

当依赖关系发生变化时,useCallback 钩子会接受你传入的函数并替换它存储的函数.当你调用回调函数时,它会调用版本的函数.

When the dependencies change, the useCallback hook will take the function you pass in and replace the function it has stored. When you call the callback, it will call the new version of the function.

换句话说,没有冻结"/有条件更新的变量——它只是存储一个函数然后重新使用它,没有比这更花哨的了:)

So in other words, there's no "frozen"/conditionally updated variables - it's just storing a function and then re-using it, nothing more fancy than that :)

这是一个演示纯 JavaScript 中发生的事情的示例:

Here's an example that demonstrates what's going on in pure JavaScript:

// React has some component-local storage that it tracks behind the scenes.
// useState and useCallback both hook into this.
//
// Imagine there's a 'storage' variable for every instance of your
// component.
const storage = {};

function useState(init) {
  if (storage.data === undefined) {
    storage.data = init;
  }
  
  return [storage.data, (value) => storage.data = value];
}

function useCallback(fn) {
  // The real version would check dependencies here, but since our callback
  // should only update on the first render, this will suffice.
  if (storage.callback === undefined) {
    storage.callback = fn;
  }

  return storage.callback;
}

function MyComponent() {
  const [data, setData] = useState(0);
  const callback = useCallback(() => data);

  // Rather than outputting DOM, we'll just log.
  console.log("data:", data);
  console.log("callback:", callback());

  return {
    increase: () => setData(data + 1)
  }
}

let instance = MyComponent(); // Let's 'render' our component...

instance.increase(); // This would trigger a re-render, so we call our component again...
instance = MyComponent();

instance.increase(); // and again...
instance = MyComponent();

这篇关于React Hooks 如何使用Callback“冻结"?关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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