如何在初始 render/re-renders 之后根据 DOM 节点信息设置状态? (反应)

How to set state based off DOM node info after initial render/re-renders? (React)

在我的框架中,我需要在初始渲染和重新渲染后 DOM 内关于我的 React 组件的 状态的某些信息,然后我需要将这些信息传递给子组件作为 context.

具体来说,我需要知道呈现的 DOM 节点是否是其父节点的 first/last 子节点,并将此信息保持为状态,所以我正在做类似的事情:

componentDidUpdate() {
  if (this.REF.current === this.REF.current.parentNode.firstChild) {
    this.setState({ isFirstChild: true });
  }
}

在这里调用 setState 会触发重新渲染,这是必需的,以便可以将值传递给子组件,我正在通过 context - 类似(精简):

render() {
  const contextValues = {
    ...this.context,
    ...this.state
  }

  return (
    <ContextProvider value={contextValues}>
      {this.props.children}
    </ContextProvider>
  );
}

...现在在我的子组件中我可以this.context.isFirstChild确定父组件是否是其父组件的第一个子组件。

问题...

设置状态会导致重新渲染。重新渲染会导致设置状态。这将 React 设置为无限循环,产生此错误:

Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate

我似乎很清楚,某些地方 我的方法是错误的。我只是不确定是什么。我认为我不应该在这里使用 setState,但是我错过了将父状态作为上下文传递给子状态的关键重新渲染。

试试这个:

componentDidUpdate() {
  if (this.REF.current === this.REF.current.parentNode.firstChild) {
    if (!this.state.isFirstChild) {
        this.setState({ isFirstChild: true });
    }        
  }
}

这样,您就不会重复调用 setState 并使用您所在州已有的相同信息。

问题是每次您更新组件时,您都会在没有任何中断条件的情况下再次更新它。这会创建一个无限循环。在此处更新之前,您应该检查 this.state.isFirstChild 不是 true

替换少量代码适合您。

      if (!this.state.isFirstChild) {
          this.setState({
              isFirstChild: true
          });
      }