gpt4 book ai didi

javascript - React 如何在状态更改后更新组件及其子组件?

转载 作者:行者123 更新时间:2023-12-05 02:35:08 24 4
gpt4 key购买 nike

我在看Paul O Shannessy - Building React From Scratch

我非常了解安装过程,但我很难理解 React 如何更新组件及其子组件

协调器通过这种方式控制更新过程:

function receiveComponent(component, element) {
let prevElement = component._currentElement;
if (prevElement === element) {
return;
}

component.receiveComponent(element);
}

Component.receiveComponent

 receiveComponent(nextElement) {
this.updateComponent(this._currentElement, nextElement);
}

这是 Component.updateComponent 方法:

  updateComponent(prevElement, nextElement) {
if (prevElement !== nextElement) {
// React would call componentWillReceiveProps here
}

// React would call componentWillUpdate here

// Update instance data
this._currentElement = nextElement;
this.props = nextElement.props;
this.state = this._pendingState;
this._pendingState = null;

let prevRenderedElement = this._renderedComponent._currentElement;
let nextRenderedElement = this.render();

if (shouldUpdateComponent(prevRenderedElement, nextRenderedElement)) {
Reconciler.receiveComponent(this._renderedComponent, nextRenderedElement);
}
}

这是在状态更改后更新组件的代码部分,我认为它也应该更新子组件,但我不明白这段代码是如何实现的,在安装过程中 React 实例化组件以进行潜水在树的更深处但这并没有发生在这里,我们需要找到第一个 HTML 元素然后我们可以改变我们的策略并在代码的另一个地方更新那个 HTML 元素,我找不到任何方法来找到任何 HTML这样的元素。

找到第一个 HTML 是停止这种无休止递归的方法,从逻辑上讲,这是我对代码的期望,在安装过程中以相同的方式停止递归,但在安装过程中,这需要组件实例化,因此我们可以委托(delegate)给协调器会发现我们处理的是 HTML 元素的包装器实例,而不是自定义组件的包装器实例,然后 React 可以将该 HTML 元素放入 DOM 中。

我不明白代码在更新过程中是如何工作的。我看到的这段代码不会深入到树中,我认为不会更新子元素,也不会让 React 找到第一个 HTML 元素,因此 React 可以更新 DOM 元素,不是吗?

这是 Github 上的代码库

最佳答案

我创建了一个 codesandbox 来深入研究

这里是 the codesandbox I created

这是一个简短的recording我打开调试器并看到调用堆栈。

工作原理

从您停止的地方开始,Component.updateComponent:

  updateComponent(prevElement, nextElement) {
//...
if (shouldUpdateComponent(prevRenderedElement, nextRenderedElement)) {
Reconciler.receiveComponent(this._renderedComponent, nextRenderedElement);
//...

Component.updateComponent 方法中调用 Reconciler.receiveComponent 调用 component.receiveComponent(element);

现在,此 component 引用 this._renderedComponent 并且不是 Component 的实例,而是 DOMComponentWrapper 的实例

下面是 DOMComponentWrapper 的 receiveComponent 方法:

  receiveComponent(nextElement) {
this.updateComponent(this._currentElement, nextElement);
}

updateComponent(prevElement, nextElement) {
// debugger;
this._currentElement = nextElement;
this._updateDOMProperties(prevElement.props, nextElement.props);
this._updateDOMChildren(prevElement.props, nextElement.props);
}

然后 _updateDOMChildren 结束调用子 render 方法。

这是我创建的用于挖掘的 codesandbox 中的调用堆栈。

call stack from setState until child render

我们如何在 DOMComponentWrapper 中结束

ComponentmountComponent 方法中,我们有:

let renderedComponent = instantiateComponent(renderedElement);
this._renderedComponent = renderedComponent;

instantiateComponent 中我们有:

  let type = element.type;

let wrapperInstance;
if (typeof type === 'string') {
wrapperInstance = HostComponent.construct(element);
} else if (typeof type === 'function') {
wrapperInstance = new element.type(element.props);
wrapperInstance._construct(element);
} else if (typeof element === 'string' || typeof element === 'number') {
wrapperInstance = HostComponent.constructTextComponent(element);
}

return wrapperInstance;

HostComponent 正在 dilithium.js 主文件中注入(inject) DOMComponentWrapper:

HostComponent.inject(DOMComponentWrapper);

HostComponent 只是一种代理,旨在反转控制并允许在 React 中使用不同的 Host。

这是注入(inject)方法:

function inject(impl) {
implementation = impl;
}

construct 方法:

function construct(element) {
assert(implementation);

return new implementation(element);
}

当我们没有 DOMComponentWrapper 时

如果我们正在更新一系列非主机组件,例如:

const Child = <div>Hello</div>

const Parent = () => <Child />

Child 如何从 Parent 的更新中呈现?

Parent Component 具有以下内容:

  • _renderedComponent 是 Child 的一个实例(也是一个 Component)
    • renderedComponent 有一个 Child 实例,因为它获取“根”元素(由 render 方法返回的元素)的类型

所以 Reconciler.receiveComponent(this._renderedComponent, nextRenderedElement) 将调用 Child 的 component.receiveComponent(element),后者又调用 this.updateComponent (this._currentElement, nextElement);(属于 Child)调用它的 render 方法(let nextRenderedElement = this.render();)

关于javascript - React 如何在状态更改后更新组件及其子组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70626534/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com