React Hooks 如何使用 Callback "freezes" 闭包?
How does React Hooks useCallback "freezes" the closure?
我想知道 React 如何在使用 useCallback
钩子(以及其他钩子)时 "freezes" 闭包,然后仅在您通过时更新钩子内使用的变量它们进入 inputs
参数。
我理解 "freeze" 可能不是很清楚,所以我创建了一个 REPL.it 来表达我的意思:https://repl.it/repls/RudeMintcreamShoutcast。打开代码后,打开 Web 浏览器控制台并开始单击 count
按钮。
对于同一个变量,外部值与内部值相比如何不同,如果它们处于相同的闭包下并引用相同的东西?我不熟悉 React 代码库,所以我想我在这里遗漏了一个幕后实现细节,但我试着想了几分钟它是如何工作的,但无法很好地理解 React 是如何工作的实现那个。
第一次呈现组件时,useCallback
挂钩会将传递的函数作为其参数并将其存储在幕后。当您调用回调时,它会调用您的函数。到目前为止,还不错。
第二次渲染组件时,useCallback
钩子会检查你传入的依赖项。如果它们没有改变,你传入的函数将被完全忽略!当您调用回调时,它将调用您在第一次渲染时传入的函数,该函数仍然引用该时间点的相同值。这与您作为依赖项传递的值无关 - 它只是正常的 JavaScript 闭包!
当依赖发生变化时,useCallback
钩子会把你传入的函数取下来,替换掉它存储的函数。当您调用回调时,它将调用函数的 new 版本。
所以换句话说,没有 "frozen"/有条件地更新变量 - 它只是存储一个函数然后重新使用它,没有比这更花哨的了:)
编辑: 这是一个示例,演示了纯 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 如何在使用 useCallback
钩子(以及其他钩子)时 "freezes" 闭包,然后仅在您通过时更新钩子内使用的变量它们进入 inputs
参数。
我理解 "freeze" 可能不是很清楚,所以我创建了一个 REPL.it 来表达我的意思:https://repl.it/repls/RudeMintcreamShoutcast。打开代码后,打开 Web 浏览器控制台并开始单击 count
按钮。
对于同一个变量,外部值与内部值相比如何不同,如果它们处于相同的闭包下并引用相同的东西?我不熟悉 React 代码库,所以我想我在这里遗漏了一个幕后实现细节,但我试着想了几分钟它是如何工作的,但无法很好地理解 React 是如何工作的实现那个。
第一次呈现组件时,useCallback
挂钩会将传递的函数作为其参数并将其存储在幕后。当您调用回调时,它会调用您的函数。到目前为止,还不错。
第二次渲染组件时,useCallback
钩子会检查你传入的依赖项。如果它们没有改变,你传入的函数将被完全忽略!当您调用回调时,它将调用您在第一次渲染时传入的函数,该函数仍然引用该时间点的相同值。这与您作为依赖项传递的值无关 - 它只是正常的 JavaScript 闭包!
当依赖发生变化时,useCallback
钩子会把你传入的函数取下来,替换掉它存储的函数。当您调用回调时,它将调用函数的 new 版本。
所以换句话说,没有 "frozen"/有条件地更新变量 - 它只是存储一个函数然后重新使用它,没有比这更花哨的了:)
编辑: 这是一个示例,演示了纯 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();