函数式组件中,函数内多重调用如何获取最新的 state 值? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
s609926202
V2EX    React

函数式组件中,函数内多重调用如何获取最新的 state 值?

  •  
  •   s609926202
    shangdev 2023-06-26 13:56:57 +08:00 2179 次点击
    这是一个创建于 838 天前的主题,其中的信息可能已经有所发展或是发生改变。

    react 函数式组件中,在 func1 函数内调用 func2 ,func2 更新 messages 后,再调用 func2 ,此时 func2 内打印的 messages 值还是个初始值?

    场景是使用 openai function call 的时候。

    代码如下:

    export default function xx(props) { const { messages, appendMsg } = useMessages(initialMessages); function func1() { func2(); } function func2() { console.log(messages); appendMsg({xx}); appendMsg({yy}); func2(); } return ( <button OnClick={func1}>Call func1</button> ); } 
    第 1 条附言    2023-06-26 14:54:56 +08:00

    用useRef获取了最新的state值:

    const messagesRef = useRef(messages); useEffect(() => { messagesRef.current = messages; }, [messages]); 
    18 条回复    2023-08-10 08:48:04 +08:00
    KMpAn8Obw1QhPoEP
        1
    KMpAn8Obw1QhPoEP  
       2023-06-26 14:08:35 +08:00 via Android
    你这不无限递归了吗
    ewiglicht
        2
    ewiglicht  
       2023-06-26 14:11:14 +08:00
    daydreamcafe
        3
    daydreamcafe  
       2023-06-26 14:16:35 +08:00
    2 楼的文档已经很完整的解释了原理,关于你这个场景,使用回调函数的方式去更新状态可以保证每次的 state 为最新

    appendMsg((prevState) => {
    // ... 在这里做一些状态的改变,之后 return 出想要修改的状态,记得读取的状态要来自 prevState
    })
    leroy20317
        4
    leroy20317  
       2023-06-26 14:19:49 +08:00   1
    useRef
    s609926202
        5
    s609926202  
    OP
       2023-06-26 14:21:16 +08:00
    @enchilada2020 #1 openai funtion calling 就是递归吧,只有匹配到 function ,就递归
    296727
        6
    296727  
       2023-06-26 14:24:09 +08:00   1
    s609926202
        7
    s609926202  
    OP
       2023-06-26 14:28:21 +08:00
    @daydreamcafe #3 appendMsg 是第三方库( chatUI )导出的一个方法,只接收新的 msg 对象,貌似做不了回调函数这样的调用。
    Leviathann
        8
    Leviathann  
       2023-06-26 15:15:00 +08:00
    message 这个值或者引用是栈上变量,每次重新渲染,函数重新被调用,它的调用栈帧都是新的,也就是说旧的变量一旦捕获就不会随着组件的重新渲染而变更

    解决方法就是把它的值放在堆上,用一个不变的引用关系去指向它,在 react 里,这是 ref
    Leviathann
        9
    Leviathann  
       2023-06-26 15:17:16 +08:00
    另外传入 useEffect 的 callback 是在渲染完成后执行,本意也并不是用来 watch ,你是否需要这个延迟?
    s609926202
        10
    s609926202  
    OP
       2023-06-26 15:41:19 +08:00
    @Leviathann #9 没懂,哪里加延迟?是 useEffect 里加延迟吗。
    oppt
        11
    oppt  
       2023-06-26 17:41:59 +08:00
    把 message 作为参数传进 fun2
    function func2(messages) {
    console.log(messages);
    const newMessages = {xx}
    appendMsg(newMessages);
    func2(newMessages);
    }
    s609926202
        12
    s609926202  
    OP
       2023-06-26 17:43:52 +08:00
    @oppt #11 靠传递参数是不行的
    amlee
        13
    amlee  
       2023-06-27 23:23:38 +08:00
    不对啊,楼上这么多回答的,你们都清楚 op 代码中的 useMessages 是一个什么样的 hook ?
    magicdawn
        14
    magicdawn  
       2023-07-04 14:36:38 +08:00 via Android
    用 useMomoizedFn 以前叫 usePersistFn, 也是社区流产的 useEvent 或 useEventCallback
    s609926202
        15
    s609926202  
    OP
       2023-07-04 15:36:24 +08:00
    @magicdawn #14 这个也是 ahook 中提供的,为了减少引用库的数量,用 ref 处理了。
    KgM4gLtF0shViDH3
        16
    KgM4gLtF0shViDH3  
       2023-08-08 18:05:55 +08:00
    @ewiglicht 你是怎么发现官方的中文文档的,没找到任何切换语言的地方。
    ewiglicht
        17
    ewiglicht  
       2023-08-09 09:39:09 +08:00
    @bestkayle 谷歌搜索
    KgM4gLtF0shViDH3
        18
    KgM4gLtF0shViDH3  
       2023-08-10 08:48:04 +08:00
    @ewiglicht 还真有,我用英文搜就搜不到。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2692 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 14:09 PVG 22:09 LAX 07:09 JFK 10:09
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86