【问题标题】:Can I call APIs in componentWillMount in React?我可以在 React 中调用 componentWillMount 中的 API 吗?
【发布时间】:2017-08-26 13:03:02
【问题描述】:

过去 1 年我一直在研究 react。我们遵循的约定是在componentDidMount 中进行API 调用,获取数据并在数据到达后设置状态。这将确保组件已安装并且设置状态将导致重新渲染组件但我想知道为什么我们不能在componentWillMountconstructor 中设置状态

官方文档说:

componentWillMount() 在安装发生之前立即调用。它 在 render() 之前调用,因此在此方法中设置状态将 不会触发重新渲染。避免引入任何副作用或 此方法中的订阅。

上面写着setting state in this method will not trigger a re-rendering,这是我在进行 API 调用时不想要的。如果我能够获取数据并能够在componentWillMountconstructor 中设置状态(假设API 调用非常快)并且数据存在于第一个渲染中,我为什么要重新渲染有吗?

如果 API 调用很慢,那么 setState 将是异步的,并且 componentWillMount 已经返回,那么我将能够 setState 并且应该会发生重新渲染。

总的来说,我很困惑为什么我们不应该在构造函数或 componentWillMount 中进行 API 调用。有人真的可以帮助我了解在这种情况下 react 是如何工作的吗?

【问题讨论】:

  • 如果您需要,请在componentWillMount 中调用 API,这不错,但是在调用第一次渲染之前,不可能从 API 获得响应并设置适当的状态。
  • @elmeister - 如果您的 API 通过缓存层,您可能能够同步获取查询的缓存结果。
  • 相关帖子here.

标签: javascript reactjs


【解决方案1】:

1. componentWillMount 并重新渲染

比较这两个componentWillMount 方法。
一个会导致额外的重新渲染,一个不会

componentWillMount () {
  // This will not cause additional re-render
  this.setState({ name: 'Andrej '});
}

componentWillMount () {
  fetch('http://whatever/profile').then(() => {
    // This in the other hand will cause additional rerender,
    // since fetch is async and state is set after request completes.
    this.setState({ name: 'Andrej '});
  })
}

.
.
.
2.在哪里调用 API?

componentWillMount () {
  // Is triggered on server and on client as well.
  // Server won't wait for completion though, nor will be able to trigger re-render
  // for client.
  fetch('...')
}

componentDidMount () {
  // Is triggered on client, but never on server.
  // This is a good place to invoke API calls.
  fetch('...')
} 

如果您在服务器上渲染并且您的组件确实需要数据进行渲染,您应该在组件外部获取(并等待完成),然后通过 props 传递数据并将组件渲染到字符串。

【讨论】:

    【解决方案2】:

    如果您只需要在第一次运行时才需要数据并且您可以接受。您可以通过调用回调来同步设置状态。

    例如:

    componentWillMount(){
        this.setState({
                    sessionId: sessionId,                
                }, () => {
                    if (this.state.hasMoreItems = true) {
                        this.loadItems()   // do what you like here synchronously 
                    }
                });
    }
    

    【讨论】:

      【解决方案3】:

      ComponentWillMount

      现在props和state都设置好了,我们终于进入了生命周期方法的领域

      这意味着 React 期望 state 可用,因为接下来会调用 render 函数,如果缺少任何提到的状态变量,代码可能会中断,这可能会发生在 ajax 的情况下。


      Constructor

      这是您定义的地方。

      所以调用 ajax 不会更新任何状态的值,因为 ajax 是异步的,构造函数不会等待响应。理想情况下,您应该使用构造函数来设置 default/initial 值。


      理想情况下,这些函数应该是纯函数,仅取决于参数。带上ajax 会给功能带来副作用。

      是的,函数依赖于state,而使用this.setState 可能会给您带来此类问题(您已在状态中设置了值,但在下一个调用的函数中状态中缺少值)。

      这会使代码变得脆弱。如果您的 API 真的很快,您可以将此值作为参数传递,并在您的组件中检查此参数是否可用。如果是,请用它初始化您的状态。如果没有,请将其设置为默认值。另外,在 ajax 的成功功能中,您可以检查该组件的ref。如果存在,则渲染组件,您可以使用setState 或任何setter(首选) 函数调用它的state

      还请记住,当您说 API 调用非常快时,您的服务器和处理可能处于最佳速度,但您永远无法确定网络。

      【讨论】:

      • 我不是专家,所以有可能,我可能犯了错误。如果有任何不一致之处,请与您的投票一起评论。
      • 但是如果我在构造函数中放置了一些默认状态而不破坏渲染怎么办。在渲染返回后也会调用 setState,因为它会被 React 视为一个事件。 componentWillMount会怎样造成困难?
      猜你喜欢
      • 1970-01-01
      • 2018-10-23
      • 1970-01-01
      • 2017-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      相关资源
      最近更新 更多