简体   繁体   English

react 库如何重新渲染组件

[英]How does the react library rerender components

I am trying to figure out how the react library rerenders components after updating the props .我试图弄清楚 react 库在更新props后如何重新呈现组件。 Therefor I kind of monkey patched ReactDOM.render method like so:因此,我有点猴子修补ReactDOM.render方法,如下所示:

const oldRender = ReactDOM.render

ReactDOM.render = function(){
// ......
console.log("42")
  return oldRender.call(this, ...arguments, () => {
    console.log("done")
    document.dispatchEvent(new Event('react-dom-rendered'))
  })
}

This works for the first rendering cylce.这适用于第一个渲染周期。 But after the props of the rendered component changed, the console.log s are not printed anymore.但是在渲染组件的props改变后, console.log就不再打印了。 In order to figure out why I read in the docs that ReactDOM.render will only be called once .为了弄清楚为什么我在文档中ReactDOM.render只会被调用一次 So I searched through google just like through react's sources but I was not able to find out how react manages to rerender a component after a props update.所以我通过谷歌搜索,就像通过 react 的来源一样,但我无法找出 react 如何在道具更新后重新渲染组件。 Could you help me here?你能帮帮我吗?

ReactDom.render called once to mount the component into the DOM.调用一次ReactDom.render将组件挂载到 DOM 中。

On state update or on props change, React starts a Reconciliation process.在 state 更新或 props 更改时,React 启动协调过程。

When a component's props or state change, React decides whether an actual DOM update is necessary by comparing the newly returned element with the previously rendered one.当组件的 props 或 state 发生变化时,React 通过将新返回的元素与之前渲染的元素进行比较来决定是否需要进行实际的 DOM 更新。 When they are not equal, React will update the DOM.当它们不相等时,React 将更新 DOM。 This process is called “reconciliation”.这个过程被称为“和解”。

In this process, React runs a pretty simple diff algorithm while traversing a copy of Virtual DOM.在这个过程中,React 在遍历 Virtual DOM 的副本时运行了一个非常简单的diff 算法

Want to implement the Reconciliation ?想要实施和解 See Build your own React and its repo .请参阅构建您自己的 React及其存储库

function reconcileChildren(wipFiber, elements) {
  let index = 0
  let oldFiber =
    wipFiber.alternate && wipFiber.alternate.child
  let prevSibling = null

  while (
    index < elements.length ||
    oldFiber != null
  ) {
    const element = elements[index]
    let newFiber = null

    const sameType =
      oldFiber &&
      element &&
      element.type == oldFiber.type

    if (sameType) {
      newFiber = {
        type: oldFiber.type,
        props: element.props,
        dom: oldFiber.dom,
        parent: wipFiber,
        alternate: oldFiber,
        effectTag: "UPDATE",
      }
    }
    if (element && !sameType) {
      newFiber = {
        type: element.type,
        props: element.props,
        dom: null,
        parent: wipFiber,
        alternate: null,
        effectTag: "PLACEMENT",
      }
    }
    if (oldFiber && !sameType) {
      oldFiber.effectTag = "DELETION"
      deletions.push(oldFiber)
    }

    if (oldFiber) {
      oldFiber = oldFiber.sibling
    }

    if (index === 0) {
      wipFiber.child = newFiber
    } else if (element) {
      prevSibling.sibling = newFiber
    }

    prevSibling = newFiber
    index++
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM