React Hooks - 引擎盖下发生了什么?
React Hooks - What's happening under the hood?
我一直在试用 React Hooks,它们似乎确实简化了存储状态之类的事情。然而,它们似乎可以通过魔法做很多事情,我找不到一篇关于它们实际工作原理的好文章。
第一件似乎很神奇的事情是,每次调用 setXXX 方法时调用像 useState() 这样的函数会导致重新呈现功能组件 returns?
当功能组件甚至没有能力在 Mount/Unmount 上 运行 编码时,像 useEffect() 这样的东西如何伪造一个 componentDidMount?
useContext() 如何实际访问上下文以及它如何知道哪个组件正在调用它?
这甚至还没有开始涵盖所有已经出现的第 3 方挂钩,例如 useDataLoader,它允许您使用以下...
const { data, error, loading, retry } = useDataLoader(getData, id)
当数据、错误、加载和重试发生变化时如何重新渲染您的组件?
抱歉,问题很多,但我想大部分问题都可以归结为一个问题,即:
钩子背后的函数如何实际访问调用它的 functional/stateless 组件,以便它可以记住重新渲染之间的事情并使用新的重新渲染数据?
React hook利用了组件的隐藏状态,它存储在一个fiber中,一个fiber是一个对应组件实例的实体(广义上,因为功能组件不创建实例作为 class 个组件)。
是 React 渲染器为钩子提供了对相应上下文、状态等的访问权限,顺便说一下,它是 React 渲染器调用组件函数。所以它可以将组件实例与组件函数内部调用的钩子函数关联起来。
这段代码解释了它是如何工作的:
let currentlyRenderedCompInstance;
const compStates = new Map(); // maps component instances to their states
const compInstances = new Map(); // maps component functions to instances
function useState(initialState) {
if (!compStates.has(currentlyRenderedCompInstance))
compStates.set(currentlyRenderedCompInstance, initialState);
return [
compStates.get(currentlyRenderedCompInstance) // state
val => compStates.set(currentlyRenderedCompInstance, val) // state setter
];
}
function render(comp, props) {
const compInstanceToken = Symbol('Renderer token for ' + comp.name);
if (!compInstances.has(comp))
compInstances.set(comp, new Set());
compInstances.get(comp).add(compInstanceToken);
currentlyRenderedCompInstance = compInstanceToken;
return {
instance: compInstanceToken,
children: comp(props)
};
}
与 useState
如何通过 currentlyRenderedCompInstance
访问当前呈现的组件实例令牌类似,其他内置挂钩也可以执行此操作并维护此组件实例的状态。
Dan Abramov 在几天前创建了一个博客 post,其中介绍了以下内容:
https://overreacted.io/how-does-setstate-know-what-to-do/
后半部分专门介绍了有关 useState 等钩子的详细信息。
对于那些有兴趣深入了解一些实施细节的人,我在这里有一个相关的答案:
我会推荐阅读 https://eliav2.github.io/how-react-hooks-work/
它包括有关使用 React Hooks 时发生的事情的详细解释,并通过许多交互式示例进行演示。
注意 - 本文并未以技术术语解释 React 如何安排后续阶段的调用,而是演示了 React 用于安排后续阶段调用的规则。
Eliav Louski 给出的 URL in another answer 是迄今为止我遇到的最好的 React 解释。这个页面应该取代 React 的官方教程,因为它删除了 hooks 和 friends 的所有魔法。
我一直在试用 React Hooks,它们似乎确实简化了存储状态之类的事情。然而,它们似乎可以通过魔法做很多事情,我找不到一篇关于它们实际工作原理的好文章。
第一件似乎很神奇的事情是,每次调用 setXXX 方法时调用像 useState() 这样的函数会导致重新呈现功能组件 returns?
当功能组件甚至没有能力在 Mount/Unmount 上 运行 编码时,像 useEffect() 这样的东西如何伪造一个 componentDidMount?
useContext() 如何实际访问上下文以及它如何知道哪个组件正在调用它?
这甚至还没有开始涵盖所有已经出现的第 3 方挂钩,例如 useDataLoader,它允许您使用以下...
const { data, error, loading, retry } = useDataLoader(getData, id)
当数据、错误、加载和重试发生变化时如何重新渲染您的组件?
抱歉,问题很多,但我想大部分问题都可以归结为一个问题,即:
钩子背后的函数如何实际访问调用它的 functional/stateless 组件,以便它可以记住重新渲染之间的事情并使用新的重新渲染数据?
React hook利用了组件的隐藏状态,它存储在一个fiber中,一个fiber是一个对应组件实例的实体(广义上,因为功能组件不创建实例作为 class 个组件)。
是 React 渲染器为钩子提供了对相应上下文、状态等的访问权限,顺便说一下,它是 React 渲染器调用组件函数。所以它可以将组件实例与组件函数内部调用的钩子函数关联起来。
这段代码解释了它是如何工作的:
let currentlyRenderedCompInstance;
const compStates = new Map(); // maps component instances to their states
const compInstances = new Map(); // maps component functions to instances
function useState(initialState) {
if (!compStates.has(currentlyRenderedCompInstance))
compStates.set(currentlyRenderedCompInstance, initialState);
return [
compStates.get(currentlyRenderedCompInstance) // state
val => compStates.set(currentlyRenderedCompInstance, val) // state setter
];
}
function render(comp, props) {
const compInstanceToken = Symbol('Renderer token for ' + comp.name);
if (!compInstances.has(comp))
compInstances.set(comp, new Set());
compInstances.get(comp).add(compInstanceToken);
currentlyRenderedCompInstance = compInstanceToken;
return {
instance: compInstanceToken,
children: comp(props)
};
}
与 useState
如何通过 currentlyRenderedCompInstance
访问当前呈现的组件实例令牌类似,其他内置挂钩也可以执行此操作并维护此组件实例的状态。
Dan Abramov 在几天前创建了一个博客 post,其中介绍了以下内容:
https://overreacted.io/how-does-setstate-know-what-to-do/
后半部分专门介绍了有关 useState 等钩子的详细信息。
对于那些有兴趣深入了解一些实施细节的人,我在这里有一个相关的答案:
我会推荐阅读 https://eliav2.github.io/how-react-hooks-work/
它包括有关使用 React Hooks 时发生的事情的详细解释,并通过许多交互式示例进行演示。
注意 - 本文并未以技术术语解释 React 如何安排后续阶段的调用,而是演示了 React 用于安排后续阶段调用的规则。
Eliav Louski 给出的 URL in another answer 是迄今为止我遇到的最好的 React 解释。这个页面应该取代 React 的官方教程,因为它删除了 hooks 和 friends 的所有魔法。