React Native中如何让函数重新读取当前变量值而非使用历史值?
问题本质原因
你观察到的持续打印初始值的现象,是JavaScript闭包捕获机制导致的:
组件每次渲染都会重新执行组件函数体,生成一套全新的局部作用域。你定义的foo函数,捕获的是它被创建那一刻所属渲染作用域里的answer值。当foo被调用后卡在while(true)循环中时,它的作用域链已经锁死了当初捕获的旧值;后续组件重渲染生成的新answer值,属于全新的局部作用域,这个正在运行的旧foo没有任何路径可以访问到。
可实现的读取最新值的方案
有完全匹配需求的实现方式,不需要中断已经运行的foo函数,就能让它实时拿到所有变量的最新值。核心逻辑是借助React中跨渲染周期保持引用稳定的useRef来中转状态值:
useRef创建的对象是和组件生命周期绑定的持久化引用,不会因为组件重渲染被重新创建,所有拿到这个引用的代码,读写的都是同一块内存上存储的值- 每次状态更新时,把最新的变量值同步写到这个ref的
current属性上 - 在持续运行的
foo循环中,不再读取局部作用域里的旧变量值,转而读取ref上存储的最新值
对应的代码实现示例:
import {useState, useRef, useEffect} from 'react'; // 原有状态定义 const [answer, setAnswer] = useState('hi'); // 创建持久化ref引用,初始值和answer保持一致 const answerRef = useRef(answer); // 当answer状态变化时,同步把最新值更新到ref上 useEffect(() => { answerRef.current = answer; }, [answer]); // 改造后的执行函数 const foo = () => { while (true) { // 每次循环读取ref上存储的当前值 console.log(answerRef.current); } };
这套实现的运行效果是:当点击按钮触发setAnswer("hello world!")后,最新的字符串会被同步写到answerRef.current上,正在循环执行的foo不需要被重新调用,下一次循环读值的时候就会打印新的"hello world!",不会一直卡在初始的"hi"。
补充说明:如果不想写额外的
useEffect同步逻辑,也可以在调用setAnswer的时候直接更新ref的值,效果完全一致:<Button onPress={() => { const newAnswer = "hello world!"; setAnswer(newAnswer); answerRef.current = newAnswer; // 直接同步更新ref存储的最新值 }} title="CLICK ME TO CHANGE THE ANSWER" />
内容的提问来源于stack exchange,提问作者CheeseBurger
相关产品推荐
相关产品推荐

