刚开始使用 react,很多属性、方法不是很熟。在此记录下我所遇到的问题及解决方法。

我在 componentWillMount() 中调用了一个异步函数,在返回结果中调用 this.setState() 来保存数据,在 render() 中使用 this.state.article 时,显示为 undefined。代码如下:

componentWillMount() {
  console.log('componentWillMount called')
  let _ = this
  // 获取当前文章 ID;
  let postID = utils.getID(ARTICLE)
 
  /**
   * @description 获取、渲染文章内容
   * @param {Number} postID - 当前文章 ID
   */
  postIO.getDetail(postID).then(res => {
    if (res.status === 200) {
      console.log('asynchronous called')
      let data = res.data
 
      _.setState({
        article: {...data},
              })
          }
  })
}
 
render() {
  console.log('render called')
  return (
    <div></div>
  )
}
 
可以看到控制台打印信息:
componentWillMount called
render called
asynchronous called
render called
 
这里可以得出:调用完 componentWillMount() 后,执行 render(),这时 componentWillMount 中的回调函数也执行完毕,更新数据后再次调用 render。
 
这个问题原因:首先,异步函数本身就是不会等前一个任务结束后再执行后一个函数,而是在执行其回调函数的同时就开始执行后一个函数了。因此,在调用完 componentWillMount 函数后,执行 postIO.getDetail(postID).then(res => {}),同时执行 render()。
 
可能导致的问题:在 componentWillMount 中的回调函数中调用 this.setState({article: {...data}}),第一次调用 render 时,是获取不到 this.state.article 的值的,这样就会引起报错。
 
解决方法:
增加一个加载状态,默认为 false,调用 componentWillMount() 时,设置为 true,当这个加载状态是 true 时,暂不渲染,当回调函数执行完毕后,设置为 false,此时再调用 render();
 
完整代码如下:
constructor(props) {
  super(props)
  
  this.state = {
    article: {},
    isLoading: false,
  }
}
componentWillMount() {
  let _ = this
  // 获取当前文章 ID;
  let postID = utils.getID(ARTICLE)
 
  _.setState({isLoading: true})
 
  /**
   * @description 获取、渲染文章内容
   * @param {Number} postID - 当前文章 ID
   */
  postIO.getDetail(postID).then(res => {
    if (res.status === 200) {
      console.log('asynchronous called')
      let data = res.data
 
      _.setState({
        article: {...data},
        isLoading: false
              })
          }
  })
}
 
render() {
  let {isLoading} = this.state
  if (isLoading) {
    return <p>isLoading...</p>
  }
  return (
    <div></div>
  )
}

react 在 componentWillMount() 中调用异步函数时,componentWillMount() finishes after render()的更多相关文章

  1. 关于在C#中构造函数中调用虚函数的问题

    在C#中如果存在类的继承关系,应避免在构造函数中调用虚函数.这是由于C#的运行机制造成的,原因如下: 新建一个类实例时,C#会先初始化该类(对类变量赋值,并将函数记在函数表中),然后再初始化父类.构造 ...

  2. Winform同步调用异步函数死锁原因分析、为什么要用异步

    1.前言 几年前,一个开发同学遇到同步调用异步函数出现死锁问题,导致UI界面假死.我解释了一堆,关于状态机.线程池.WindowsFormsSynchronizationContext.Post.co ...

  3. Lua中调用C函数

    Lua利用一个虚拟的堆栈来给C传递值或从C获取值.每当Lua调用C函数,都会获得一个新的堆栈,该堆栈初始包含所有的调用C函数所需要的参数值(Lua传给C函数的调用实参),并且C函数执行完毕后,会把返回 ...

  4. C中调用Lua函数

    我们先来看一个简单的例子: lua_State* L = NULL; // 内部调用lua函数 double f(double x, double y) { double z; lua_getglob ...

  5. C++箴言:避免构造或析构函数中调用虚函数

    如果你已经从另外一种语言如C#或者Java转向了C++,你会觉得,避免在类的构造函数或者析构函数中调用虚函数这一原则有点违背直觉.但是在C++中,违反这个原则会给你带来难以预料的后果和无尽的烦恼. 正 ...

  6. 读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数

    关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样.如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为 ...

  7. 【校招面试 之 C/C++】第10题 C++不在构造函数和析构函数中调用虚函数

    1.不要在构造函数中调用虚函数的原因 在概念上,构造函数的工作是为对象进行初始化.在构造函数完成之前,被构造的对象被认为“未完全生成”.当创建某个派生类的对象时,如果在它的基类的构造函数中调用虚函数, ...

  8. Lua中调用C函数(lua-5.2.3)

    Lua能够调用C函数的能力将极大的提高Lua的可扩展性和可用性. 对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们全然能够通过C函数来实现,之后再通过Lua调用指定的C函数. 对于那些可 ...

  9. Effective C++ .09 不在构造和析构过程中调用virtual函数

    看过C++对象模型的话就可以知道,在构造基类时,完整的vtable没有建立起来(表项没有被相应的子类函数替换),因而无法调用到子类的函数(即构造函数中的virtual函数是本类里的方法,不是virtu ...

随机推荐

  1. TensorFlow 官方文档中文版 --技术文档

    1.文档预览 2.文档下载 TensorFlow官方文档中文版-v1.2.pdf 提取码:pt7p

  2. Failed to process import candidates for configuration class [com.simple.....]

    主要原因: 是因为自己定制的starter在打包时(package)用了spring-boot-maven-plugin,即在你的定制starter工程的pom.xml中有如下配置: <buil ...

  3. ORACLE中使用row_number over()排序

    from:http://blog.csdn.net/iw1210/article/details/11937085 意图:实现select top 1 * from tablename Oracle  ...

  4. Vue(九) 自定义指令

    前面介绍了许多 Vue 内置的指令,比如 v-if.v-show等,这些丰富的指令能满足我们绝大部分的业务需求,不过在需要一些特殊功能时,我们仍然希望对 DOM 进行底层的操作,这时就要用到自定义指令 ...

  5. C++获取网络数据

    1.  获取数据 工具libcurl libcurl主要功能就是用不同的协议连接和沟通不同的服务器.libcurl当前支持http, https, ftp, gopher, telnet, dict, ...

  6. Win10系列:C#应用控件基础18

    WebView控件 使用WebView控件可以在应用中添加一个简易的网页浏览器窗口,将指定地址的网页内容显示出来,并可以通过WebView控件所提供的方法.属性及事件,实现如页面导航.HTML文本解析 ...

  7. Java toBinaryString()函数探究及Math.abs(-2147483648)=-2147483648原理探究

    toBinaryString()函数 public class Customer { public static void main(String[] args) { int m=-8; System ...

  8. 3D打印GCODE文件学习(一)

    我家有一个天威的入门级的3D打印机.它有一个配套的软件叫“Rrint-RiteCoLiDo Repetier-Host V1.5.5”,用来连接.控制打印机.同时它可以加载各种切片软件,对各种3D模型 ...

  9. VMware与Centos系统安装、重置root密码

    VMware与Centos系统安装   今日任务 .Linux发行版的选择 .vmware创建一个虚拟机(centos) .安装配置centos7 .xshell配置连接虚拟机(centos) 选择性 ...

  10. centos重置密码

    重置root密码:   法一:                1.开机按e                2.将linux 16后的ro改为rw init=/sysroot/bin/          ...