【问题标题】:How does React provide independent contexts for subtrees?React 如何为子树提供独立的上下文?
【发布时间】:2021-05-11 04:27:41
【问题描述】:

如果作为一个思想实验,我要为 JSX 编写自己的 createElement 实现,那么支持 implicit context 会是什么样子?

特别是,我无法弄清楚 JSX 的 createElement 签名的有限手段如何使不同子树的上下文独立。 (看起来 React 的上下文处理在最近的版本中变得更加精细;我最感兴趣的是 earlier versions 看似更直接的机制。)

这可能用于automatically determine heading levels,例如:

<Section title="Hello World">
    <Card title="Details" />
</Section>
<Card title="Example" />

这里Card 会自动生成&lt;h3&gt;&lt;h2&gt;,分别依赖于context.headingLevel 之类的东西。

【问题讨论】:

  • 我真的很想回答这个问题,但不确定您期望的答案是什么,首先,您询问可能的实现,为每个组件设置诸如嵌套级别之类的元数据就可以了。你也问context是如何独立的,但是和createElement没有关系,想想你可以用HOC实现context,所以基本上可以将context值注入到所有子树中。
  • 至少旧版本的 React(显然是<16.3.0)设法为所有组件提供context,而组件作者没有明确选择 - 所以我想知道他们是如何管理的。当然,答案必须在createElement 的(无状态?)实现中,因为这就是 JSX 所允许的全部?

标签: reactjs jsx


【解决方案1】:

一个非常好的问题,它显示了创建 React 元素的概念与实际执行渲染函数的概念有多么不同(类组件的 .render 方法或只是功能组件的主体)。

在 JSX 本身(只是 React.createElement(…))中根本没有“上下文”的概念。它仅在组件被渲染时才存在。实际实现 Context API 确实是 React Renderer(例如 React DOM 或 React Native)的职责。

如果您删除了存储状态和更新 UI 的功能,您将得到一个仅“渲染一次”的最小 React 实现,但完全可以理解手头的问题。

每次 React Renderer 需要渲染 React Elements 树(例如使用 JSX 构建的树)时,它都会传递每个元素并将其转换为 DOM 结构,但是当它遇到组件节点(不是“原生”元素)时它需要渲染它以获得 its React Element 子树,并与它交换原始节点。

正是在这个特定的时刻,React 可以跟踪哪些 Context 值将传递给哪些组件,因为它正在遍历树。

因此,要直接回答您的问题,您不能在“元素创建阶段”中实现上下文,在您的 JSX 实现中,您需要在可以遍历树的后续阶段执行。

如果您尝试构建“即时 JSX”,您可能会遇到这样的情况:

function createElement(type, props, ...children) {
  props = { children, ...props };

  if (typeof type === 'function') {
    return type(props);
  } else {
    return { type, props };
  }
}

在这种情况下,您将无法实现类似于上下文的 API,因为执行顺序是先内后外:

const div = createElement('div', {}, createElement(Card, {}));
// identical to
const card = createElement(Card, {}); // inner, and then…
const div = createElement('div', {}, card); // outer

【讨论】:

  • 谢谢,这是我的怀疑,但你的解释肯定填补了一些空白。我仍然很好奇 React 的渲染器究竟是如何管理上下文跟踪/分配的,但这可能太复杂了,无法在这个场所进行解释。无论哪种方式,我都会再看一下 React 的源代码。
  • 了解 React 内部结构的最佳方式是自己构建一个 React,这正是你现在的做法!请继续这个旅程!如果你需要一个非常好的资源,我可以给你指点这个很棒的指南:pomb.us/build-your-own-react
  • 谢谢你提醒我;这确实是一个令人印象深刻的指南——虽然它似乎没有解决上下文,所以更多的是一般用途。
猜你喜欢
  • 2019-12-21
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多