【问题标题】:How to set state based off DOM node info after initial render/re-renders? (React)如何在初始渲染/重新渲染后根据 DOM 节点信息设置状态? (反应)
【发布时间】:2019-12-13 20:08:48
【问题描述】:

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

具体来说,我需要知道渲染的 DOM 节点是否是其父节点的第一个/最后一个子节点,并将此信息保持为状态,所以我正在做类似的事情:

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,但是我错过了将父状态作为上下文传递给子状态的关键重新渲染。

【问题讨论】:

  • 有没有其他方法可以确定给定的孩子是否是第一个?这是关于使用一些 3rd 方库或类似的东西对表格进行排序吗?无论如何,主要问题是Re-rendering causes a set-state.render() 不得更改状态。永远。
  • 我无法确定任何其他方式 - 我认为可能有一种不依赖 DOM 的方式,但似乎没有。我正在为 React 构建一个 css-in-js 工具并尝试模拟某些伪选择器的行为。
  • 是否可以在codesandbox.io 上创建minimal reproducible example
  • @ChrisG 在代码框codesandbox.io/s/wispy-river-wglp2上似乎有完全不同的错误@

标签: javascript reactjs state rerender


【解决方案1】:

试试这个:

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

这样,您不会重复调用 setState 并使用您的状态中已有的相同信息。

【讨论】:

  • 我最初想尝试这样的东西,理论上是有道理的,让我试一试
【解决方案2】:

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

替换少量代码对你有用。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-02
    • 2021-02-09
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    相关资源
    最近更新 更多