React JS中调用特定props更改组件方法的正确模式是什么?

Pen*_*ica 10 javascript lifecycle reactjs react-native redux

使用React和Redux,假设您有一个将请求发送到外部API的组件方法.

import React, { Component } from 'react';
import { connect } from 'react-redux';

class MyComp extends Component {

  boolUpdate (val) {
    fetch('http://myapi.com/bool', { val });
  }

  shouldComponentUpdate (nextProps) {
    return false;
  }

  render () {
    return <h1>Hello</h1>;
  }

}

const mapStateToProps = ({ bool }) => ({ bool });

export default connect(mapStateToProps)(MyComp);
Run Code Online (Sandbox Code Playgroud)

现在假设您希望boolUpdate()每次调整boolprop时调用,但这不应该触发组件更新,因为组件的渲染中没有任何内容受到影响.

在React中执行此操作的最佳方法是什么?

直到最近,人们常常做类似的事情:

componentWillReceiveProps (nextProps) {
  if (nextProps.bool !== this.props.bool) this.boolUpdate(nextProps.bool);
}
Run Code Online (Sandbox Code Playgroud)

但是从React v16.3开始componentWillReceiveProps()已被弃用.在这个例子中,我们也不能使用它们componentDidUpdate(),因为shouldComponentUpdate()可以防止这种情况发生.并且getDerivedStateFromProps()是静态方法,因此它无权访问实例方法.

因此,我们留下的唯一选择似乎是使用shouldComponentUpdate()自己.有点像:

shouldComponentUpdate (nextProps) {
  if (nextProps.bool !== this.props.bool) this.boolUpdate(nextProps.bool);
  return false;
}
Run Code Online (Sandbox Code Playgroud)

这看起来对我来说相当"hacky",而不是为我shouldComponentUpdate()设计的.

有没有人有更好的模式建议?

是否有一种倾听特定道具变化和触发组件方法的首选方法?

谢谢!

Dan*_*mov 5

如果你想在道具改变时运行一些代码(例如数据获取),那就去做吧componentDidUpdate.

componentDidUpdate(prevProps) {
  if (prevProps.id !== this.props.id) {
    this.fetchData();
  }
}
Run Code Online (Sandbox Code Playgroud)

在您的示例中,这将无效,因为shouldComponentUpdate返回false.我认为这不是一个非常常见的情况,因为通常你仍然想要在道具改变的情况下重新渲染.

例如,如果用户ID更改,您可能希望在加载新用户的数据时显示加载指示符.因此,在这种情况下,避免重新渲染并不是很有用.

但是,如果您完全确定两者都需要阻止重新渲染并且需要执行副作用,例如在道具更改中获取数据,则可以将组件拆分为两个.外部组件将执行数据提取componentDidUpdate并返回<InnerComponent {...this.props} />.内部组件将具有shouldComponentUpdate防止进一步重新呈现的实现.同样,我不希望这是一个常见的情况,但你可以做到这一点.


Mat*_*obi 4

根据 React文档和github 上的讨论,根据 props 更改获取新数据的地方实际上是componentDidUpdate.

\n\n

渲染实际上分为两个阶段,一个Render Phase阶段是纯粹的,不会产生副作用,另一个阶段Commit Phase可以运行副作用,使用 DOM 并安排更新。

\n\n

您可以在 Dan Abramov 的图表中看到很好的解释:\n在此输入图像描述

\n\n

丹还提到:

\n\n
\n

人们过去常常在 componentWillReceiveProps 中混合这两种不同的东西,这就是为什么我们必须将其分成一个纯方法 (getDerivedStateFromProps) 和一个现有的不纯方法,其中 xe2x80x99 可以产生副作用(组件更新)。

\n
\n\n

对于解决方案本身,我附上了文档中的示例:

\n\n
\n

当 props 改变时获取外部数据

\n\n

下面是一个根据 props 值获取外部数据的组件示例:

\n\n

前:

\n\n
componentDidMount() {\n  this._loadAsyncData(this.props.id);\n}\n\ncomponentWillReceiveProps(nextProps) {\n  if (nextProps.id !== this.props.id) {\n    this.setState({externalData: null});\n    this._loadAsyncData(nextProps.id);\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

后:

\n\n
  static getDerivedStateFromProps(nextProps, prevState) {\n    if (nextProps.id !== prevState.prevId) {\n      return {\n        externalData: null,\n        prevId: nextProps.id,\n      };\n    }\n    return null;\n  }\n\n  componentDidMount() {\n    this._loadAsyncData(this.props.id);\n  }\n\n  componentDidUpdate(prevProps, prevState) {\n    if (this.state.externalData === null) {\n      this._loadAsyncData(this.props.id);\n    }\n  }\n
Run Code Online (Sandbox Code Playgroud)\n
\n