javascript - React数据获取为什么一定要在componentDidMount里面调用?
ringa_lee
ringa_lee 2017-04-11 11:30:06
[JavaScript讨论组]

根据文档说法,从后台获取数据一定要放在componentDidMount里面调用,为什么不能在constructor或者componentWillMount里面调用?有什么不同?

ringa_lee
ringa_lee

ringa_lee

全部回复(6)
巴扎黑

这与React组件的生命周期有关,组件挂载时有关的生命周期有以下几个:

  • constructor()

  • componentWillMount()

  • render()

  • componentDidMount()

上面这些方法的调用是有次序的,由上而下,也就是当说如果你要获取外部数据并加载到组件上,只能在组件"已经"挂载到真实的网页上才能作这事情,其它情况你是加载不到组件的。

componentDidMount方法中的代码,是在组件已经完全挂载到网页上才会调用被执行,所以可以保证数据的加载。此外,在这方法中调用setState方法,会触发重渲染。所以,官方设计这个方法就是用来加载外部数据用的,或处理其他的副作用代码。

constructor被调用是在组件准备要挂载的最一开始,所以此时组件尚未挂载到网页上。

componentWillMount方法的调用在constructor之后,在render之前,在这方法里的代码调用setState方法不会触发重渲染,所以它一般不会用来作加载数据之用,它也很少被使用到。

一般的从后台(服务器)获取的数据,都会与组件上要用的数据加载有关,所以都在componentDidMount方法里面作。虽然与组件上的数据无关的加载,也可以在constructor里作,但constructor是作组件state初绐化工作,并不是设计来作加载数据这工作的,所以所有有副作用的代码都会集中在componentDidMount方法里。


补充一下,Redux作初始数据载入时,是可以不需透过React组件的生命周期方法,大致的方式如下代码:

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './App'

// reducer
function items(state = [], action) {
  switch (action.type) {
    case 'LOAD_ITEMS':
      return [...action.payload]
    default:
      return state
  }
}

// 创建store
const store = createStore(items)

fetch('http://localhost:8888/items', {
  method: 'GET'
})
.then((response) => {
  // ok代表状态码在200-299
  if (!response.ok) throw new Error(response.statusText)
  return response.json()
})
.then((itemList) => {
  // 作dispatch动作,载入外部数据完成之后
  store.dispatch({ type: 'LOAD_ITEMS', payload: itemList })
})
.catch((error) => { throw new Error(error.message) })

// React组件加载到真实DOM上
ReactDOM.render(
<Provider store={store}>
 <App />
</Provider>, document.getElementById('root'))

为何可以这样作的原因,是Redux的store中的状态有一个最初始的值(reducer上传参里的默认值),组件先初始化完成,接著异步的fetch用promise语法,在作完外部数据加载后,发送动作出来,此时reducer更动store里的状态,react-redux绑定器会触发React组件的重渲染,所以组件上数据会自动更新。

有问题再问吧,代码写得简略但测试过是可执行的。

伊谢尔伦

constructor()中获取数据的话,如果时间太长,或者出错,组件就渲染不出来,你整个页面都没法渲染了。
componentDidMount()中能保证你的组件已经正确渲染。

PHP中文网

1、通常我在componentWillMount发送ajax(渲染dom之前做的操作)

2、componentDidMount也可以做ajax操作(渲染dom完成之后做的操作)

那么,这2种情况如何区分呢?

需求1:

当你的render函数需要有数据才能渲染的时候,就在componentWillMount做操作。
render() {
    return data && <p>{data}</p>
}

需求2:

当你的render不需要数据,先渲染dom结构,就在componentDidMount操作。
render() {
    const { data } = this.props
    return (
        <p>
            <span>我要先渲染</span>
            <span>{data || ''}</span>
        </p>
    )
}
大家讲道理

你既然了解的周期的顺序,那就很好理解了啊!willMount在dom没有渲染前先进行的方法,如果这个时候请求ajax那么势必会有等待的这一刻,然后排队渲染dom,而didMount是在dom加载后在进行的方法,而这个时候请求ajax前面没有任何等待,直接请求,然后如果你setState那么整个虚拟dom会在此渲染,此时再将获得的数据进行渲染,这样就感觉很顺的就执行下去了。而再次渲染的同时大部分的dom都是没有改变的,只有部分改变,所以渲染的速度会很快

高洛峰

因为有很多前置工作要做

PHP中文网

感谢各位的回答:
总结一下不建议在constructor和componentWillMount里写的原因是

  1. 会阻碍组件的实例化,阻碍组件的渲染

  2. 如果用setState,在componentWillMount里面触发setState不会重新渲染

而在React Redux中,由于触发的渲染方式不同,是可以不需透过React组件的生命周期方法,所以我感觉可以在生命周期的任何地方调用。当然,在consttructor和componentWillMount还是会阻碍一点点组件的实例化和渲染。

由于@eyesofkids写的全面一点,我采纳他的了。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号