Javascript 在刷新列表时,Hooks useCallback将继续使用旧值

Javascript 在刷新列表时,Hooks useCallback将继续使用旧值,javascript,reactjs,react-native,react-hooks,Javascript,Reactjs,React Native,React Hooks,下面的useCallback有什么问题?我没有在每次调用函数onRefresh时获得下面的值? 如何使用钩子使其返回预期值 调用刷新2x时的示例 期望值: true 0 20 false true 0 20 false 价值:收到 false 0 0 false false 20 20 false 状态变量的初始化 const [refreshing, setRefreshing] = useState(false) const [offsetQuestions, setOffsetQu

下面的useCallback有什么问题?我没有在每次调用函数
onRefresh
时获得下面的值? 如何使用钩子使其返回预期值

调用刷新2x时的示例

期望值:

true
0
20
false

true
0
20
false
价值:收到

false
0
0
false

false
20
20
false
状态变量的初始化

const [refreshing, setRefreshing] = useState(false)
const [offsetQuestions, setOffsetQuestions] = useState(0)
使用useCallback进行函数调用:

const fetchSomeData = async () => {
  await new Promise(resolve => setTimeout(resolve, 3000)) // 3 sec
}

const onRefresh = useCallback( async () => {
  setRefreshing(true)
  setOffsetQuestions(0)
  console.log(refreshing)
  console.log(offsetQuestions)

  await fetchSomeData()

  setOffsetQuestions(20)
  setRefreshing(false)
  console.log(offsetQuestions)
  console.log(refreshing)
}, [refreshing, offsetQuestions])
调用函数时:

<FlatList
   data={questionsLocal}
   refreshing={refreshing}
   onRefresh={onRefresh}
   ...
/>


您得到的是钩子中的预期行为。都是关于闭包的。react中的每个渲染都有自己的道具、状态、函数和事件处理程序,对于特定渲染,它们永远保持不变。所以这里发生的是,
useCallback
正在关闭该特定渲染的状态变量,因此,
console.log
即使在
setState
之后也会始终为您提供特定渲染的状态值,因为闭包

您可以使用UseRef钩子使用当前状态值而不是词法值

const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
这就是如何在引用中设置值并在任何地方使用它的方法

下面是您可以详细了解此问题并提供可能解决方案的链接


谢谢

这种情况让许多开始使用钩子的开发人员感到困惑。您可能希望React是被动的,并且在调用
setX
后会更改状态的值,但是如果您仔细想想,就不能期望React停止执行流更改状态变量并继续执行

因此,您得到的是创建
useCallback
(反复阅读)的范围内的状态变量

让我们将其分解为两部分,范围和useCallback,因为要使用
useState
useCallback
,您必须了解这两个不同的方面

范围:

假设您有一个名为
age
的状态,以及一个写入/读取该状态的函数(目前不使用
useCallback

从中可以看出,每个渲染都定义了一个新的
age
变量(如果React给出了该值),还定义了一个新的
increaseAge
函数,可以访问保存
age
变量的范围

这就是作用域的工作原理,这就是为什么在调用
setAge
之后不会得到一个新值
age
。为了能够在
age
React上获得新值,必须重新渲染组件,因此将在新范围上定义一个新的
age
变量。这正是调用
setAge
后发生的情况,React将触发新的渲染

useCallback

现在,假设您不想一次又一次地定义
increaseAge
函数,您希望保留相同的引用(可以帮助防止无用的渲染)。这是您希望使用
useCallback
的地方

使用
useCallback
时,React会为每个渲染提供相同的函数引用,除非其中一个依赖项发生更改

如果不向
useCallback
提供依赖项,React将不会重新创建函数,函数将访问创建它的作用域(第一次渲染),当向
useCallback
提供正确的依赖项时,它将重新创建,现在可以使用最新的状态变量访问作用域


这应该解释为什么必须提供依赖项,以及如何访问状态变量(作用域)。

您是否也可以回答问题的第二部分:“如何使用钩子使其返回预期值?”@justdvl正如我上面所说,您从控制台日志中得到的是react钩子中的预期行为,这一切都与闭包有关。相反,请解释为什么在调用
setRefreshing
之后,您希望立即获取/读取同一函数中的更新值,我可以帮助您解决这个问题。
const [age, setAge] = useState(42);

const increaseAge = () => {
  setAge(age + 1);   // this "age" is the same "age" from above 
  console.log(age);  // also this one
}