V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
QGabriel
V2EX  ›  React

react hooks 问题

  •  
  •   QGabriel · 2020-09-28 16:35:18 +08:00 · 2404 次点击
    这是一个创建于 1550 天前的主题,其中的信息可能已经有所发展或是发生改变。
    useEffect( () => {
    const getStatus = async () => {
    let res = await queryMedical({id: null})
    console.log(1, 'formData', formData)
    setFormData(res)
    console.log(2, 'formData', formData)
    }
    getStatus()
    }, [])
    console.log(0, 'formData', formData)

    ------------------------------------------
    0 "formData" {}
    0 "formData" {}
    1 "formData" {}

    0 "formData" {id: 170, buyerId: 10000000424, tenantId: 1, createdBy: "10000000424", createdAt: null, …}


    2 "formData" {}


    ----------------------
    第三次 0 时 formData 已经有值了.为什么还会走一次 console.log(2) 呢?
    5 条回复    2020-10-12 11:09:33 +08:00
    azcvcza
        1
    azcvcza  
       2020-09-28 18:13:30 +08:00
    我个人的看法是,hooks 是提供给虚拟机执行的闭包,而函数式组件就是给虚拟机多次执行的含有不同参数的函数,当打印了 1 之后,setFormData 触发重新渲染,再运行含有新参数的函数,然后发现 effect 中的函数已经执行过了,直接跳到 0,最后打印闭包中剩下没执行的 2 ?
    onfuns
        2
    onfuns  
       2020-09-28 18:17:41 +08:00
    useState 里的 callback 调用其实是异步的,所以不能在调用 callback 后立马获取 console.log(2, 'formData', formData),这种写法是错误的。
    JimmyChange
        3
    JimmyChange  
       2020-09-28 19:14:52 +08:00
    console.log(1, 'formData', formData)
    setFormData(res)
    console.log(2, 'formData', formData)

    调用 setFormData 会再次触发 render,输出 0 formData,但是 setFormData 结束后,后边的 console.log 还是会执行,输出 2 "formData"
    baxtergu
        4
    baxtergu  
       2020-09-29 09:23:49 +08:00
    按照你的写法:
    1 、useEffect 中的代码只会在组件 mount 以后执行一次,不管以后组件状态或者 props 怎么变 useEffect 中的代码只会执行 1 次。(也就是为什么 1 和 2 只会输出一次,而 0 会输出多次)
    2 、useState 生成的 setState 的执行是**创建一个新的 state 为下一次 render 使用**。但是 useEffect 这次函数闭包里的 formData 是上一次的 state 也就是{},这一点跟类组件的 this.state 是完全不一样的。类组件的 this.state 保存的是状态对象的一个引用,但是用 useState 生成的 state 是通过闭包保存了执行 useEffect 时 state 的在函数执行上下文中的,也就是旧的 state 引用。每次重新 render 以后都会生成一个新的 state,而不是改变旧 state 的引用里的值。
    cw2k13as
        5
    cw2k13as  
       2020-10-12 11:09:33 +08:00
    useEffect( () => {
    }, [])只会执行一次,hook 保留的都是旧值,新建一个 useEffect( () => {
    console.log( 'formData', formData)
    }, [formData])才是获取新的值
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5623 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 03:21 · PVG 11:21 · LAX 19:21 · JFK 22:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.