rateltalk
V2EX  ›  React

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

  •  
  •   rateltalk ·
    shangdev · Jun 26, 2023 · 3163 views
    This topic created in 1227 days ago, the information mentioned may be changed or developed.

    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>
      );
    }
    
    Supplement 1  ·  Jun 26, 2023

    用useRef获取了最新的state值:

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

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

    解决方法就是把它的值放在堆上,用一个不变的引用关系去指向它,在 react 里,这是 ref
    Leviathann
    Leviathann
    Jun 26, 2023
    9
    另外传入 useEffect 的 callback 是在渲染完成后执行,本意也并不是用来 watch ,你是否需要这个延迟?
    rateltalk
    rateltalk
    OP
    Jun 26, 2023
    10
    @Leviathann #9 没懂,哪里加延迟?是 useEffect 里加延迟吗。
    oppt
    oppt
    Jun 26, 2023
    11
    把 message 作为参数传进 fun2
    function func2(messages) {
    console.log(messages);
    const newMessages = {xx}
    appendMsg(newMessages);
    func2(newMessages);
    }
    rateltalk
    rateltalk
    OP
    Jun 26, 2023
    12
    @oppt #11 靠传递参数是不行的
    amlee
    amlee
    Jun 27, 2023
    13
    不对啊,楼上这么多回答的,你们都清楚 op 代码中的 useMessages 是一个什么样的 hook ?
    magicdawn
    magicdawn
    Jul 4, 2023 via Android
    14
    用 useMomoizedFn 以前叫 usePersistFn, 也是社区流产的 useEvent 或 useEventCallback
    rateltalk
    rateltalk
    OP
    Jul 4, 2023
    15
    @magicdawn #14 这个也是 ahook 中提供的,为了减少引用库的数量,用 ref 处理了。
    KgM4gLtF0shViDH3
    KgM4gLtF0shViDH3
    Aug 8, 2023
    16
    @ewiglicht 你是怎么发现官方的中文文档的,没找到任何切换语言的地方。
    ewiglicht
    ewiglicht
    Aug 9, 2023
    17
    @bestkayle 谷歌搜索
    KgM4gLtF0shViDH3
    KgM4gLtF0shViDH3
    Aug 10, 2023
    18
    @ewiglicht 还真有,我用英文搜就搜不到。。。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2426 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 102ms · UTC 15:37 · PVG 23:37 · LAX 07:37 · JFK 10:37
    ♥ Do have faith in what you're doing.