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

320 天前
 s609926202

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>
  );
}
1502 次点击
所在节点    React
18 条回复
enchilada2020
320 天前
你这不无限递归了吗
ewiglicht
320 天前
daydreamcafe
320 天前
2 楼的文档已经很完整的解释了原理,关于你这个场景,使用回调函数的方式去更新状态可以保证每次的 state 为最新

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

解决方法就是把它的值放在堆上,用一个不变的引用关系去指向它,在 react 里,这是 ref
Leviathann
320 天前
另外传入 useEffect 的 callback 是在渲染完成后执行,本意也并不是用来 watch ,你是否需要这个延迟?
s609926202
320 天前
@Leviathann #9 没懂,哪里加延迟?是 useEffect 里加延迟吗。
oppt
320 天前
把 message 作为参数传进 fun2
function func2(messages) {
console.log(messages);
const newMessages = {xx}
appendMsg(newMessages);
func2(newMessages);
}
s609926202
320 天前
@oppt #11 靠传递参数是不行的
amlee
319 天前
不对啊,楼上这么多回答的,你们都清楚 op 代码中的 useMessages 是一个什么样的 hook ?
magicdawn
312 天前
用 useMomoizedFn 以前叫 usePersistFn, 也是社区流产的 useEvent 或 useEventCallback
s609926202
312 天前
@magicdawn #14 这个也是 ahook 中提供的,为了减少引用库的数量,用 ref 处理了。
bestkayle
277 天前
@ewiglicht 你是怎么发现官方的中文文档的,没找到任何切换语言的地方。
ewiglicht
276 天前
@bestkayle 谷歌搜索
bestkayle
275 天前
@ewiglicht 还真有,我用英文搜就搜不到。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/951766

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX