componentDidMount() 中的 setState() 是否被视为反模式

IT技术 reactjs
2021-03-30 09:55:03

我刚刚看了关于inside 的讨论setState()componentDidMount()

可以看到在render()函数之后,componentDidMount()React 会调用函数。当您setState()调用时,componentDidMount()您会导致整个组件树不仅重新渲染当前组件 - 不要忘记,当前组件刚刚完成渲染。

还有人建议把setState()call 放在里面componentWillMount()在某些情况下,我想获取渲染元素的高度并将其存储为状态,而上述方法不起作用。我也看了一下React官网,里面建议做Ajax调用componentDidMount(),又和上面的思路背道而驰。

那么,我把setState()里面放错了componentDidMount()吗?如果是,我应该申请什么作为替代方案?

4个回答

您可以setState()立即拨打componentDidMount()它会触发额外的渲染,但会在浏览器更新屏幕之前发生。这保证即使render()在这种情况下将被调用两次,用户也不会看到中间状态。请谨慎使用此模式,因为它通常会导致性能问题在大多数情况下,您应该能够在constructor()替代中分配初始状态但是,当您需要在渲染取决于其大小或位置的内容之前测量 DOM 节点时,对于模态和工具提示等情况,它可能是必要的

react文档

使用 DidMount 可以清楚地表明,直到初始渲染之后才会加载数据。这会提醒您正确设置初始状态,这样您就不会以导致错误的未定义状态结束。

例子

TLDR: - 如果您在构造函数中有所有需要的数据 - 在state那里分配

constructor(props) {
  super(props);
  // Don't call this.setState() here!
  this.state = { counter: 0 };
}
  • 调用异步操作,触摸 DOM componentDidMount()
感谢您的回答!如果您添加一些代码示例以及参考链接就好了
2021-05-27 09:55:03
哇,非常简洁,解释得很好。这些段落正是我需要的
2021-05-28 09:55:03
没什么大不了的,这个答案可能会被未来的读者阅读@Buggy
2021-06-01 09:55:03
@Brian - 谢谢你的格式化,你真的是个好人,我会尽量在功能中多注意这一点)
2021-06-02 09:55:03
感谢您重播。已编辑)
2021-06-09 09:55:03

您不知道渲染元素的高度的情况可能是使用setStateinside的有效借口componentDidMount但是在这种情况下,我肯定会添加另一个生命周期方法shouldComponentUpdate来控制重新渲染问题。

@WebDegBrian 是的,如果你想根据计算的状态进行渲染,那么你可能不需要shouldComponentUpdate,但这对我来说似乎是一种糟糕的反应,通常你不想在你的 js 或 ts 中逐个像素地过度控制每个组件代码。
2021-05-22 09:55:03
谢谢回答!一个小问题,如果高度状态影响了组件的渲染方式,那么shouldComponentUpdate就不需要了吧?
2021-06-07 09:55:03
您不应该shouldComponentUpdate用于控制渲染器问题,它仅作为性能优化存在该文档明确表示:“不要依赖它来‘阻止’渲染,因为这会导致错误”。
2021-06-12 09:55:03

通常你不想在里面做同步状态设置componentDidMount,你应该把它放在构造函数中。然而,元素高度有点独特,因为在它被挂载并渲染到 DOM 之前,你实际上无法获得元素的高度。

所以通常不会,但在元素高度的情况下,可以在componentDidMount.

很好的答案,非常感谢
2021-05-25 09:55:03
你能告诉我为什么我不能在 componentDidMount 中同步调用 setState 吗?
2021-06-18 09:55:03

您可以执行异步调用,并且必须在 componentDidMount() 生命周期挂钩内执行。但这将再次调用渲染方法。

如果您不希望重新渲染再次发生,请使用 shouldComponentUpdate() 方法来防止重新渲染 DOM。示例如下:

shouldComponentUpdate (nextProps, nextState) {
    // check the condition here
    if (nextState.something !== 'value') {
         // stop re-rendering
         return false;
    }
    // continue rendering
    return true;
}