提问人:Maciej 提问时间:5/13/2023 更新时间:10/13/2023 访问量:182
React Custom Hook 中的闭包问题
Closure Issue in React Custom Hook
问:
我想知道这是怎么回事。我终于将变量 curPage
移动到我的自定义钩子中的全局范围,因为闭包由于某种奇怪的原因不起作用。太好了......问题解决了,但它看起来并不优雅,我真的很担心为什么?
这个钩子负责分页,但它做什么并不重要。保存该值的变量很重要,因为它是每次函数运行时递增的值。let curPage = 1;
getItems
import { useState } from 'react';
// let curPage = 1; I MOVED IT HERE AND WORKS BUT ... well
const usePagination = items => {
const [itemsToRender, setItemsToRender] = useState(items.slice(0, 4));
let curPage = 1;
let maximumItems = 4;
let totalPages = Math.ceil(items.length / maximumItems);
//get 4 items per each page;
const getItems = () => {
curPage += 1;
const min = (curPage - 1) * maximumItems;
const max = curPage * maximumItems;
setItemsToRender(state => state.concat(items.slice(min, max)));
};
return { getItems, itemsToRender, curPage, totalPages };
};
export default usePagination;
钩子在一些 React 组件函数中被调用,我立即解构返回的对象。
const { getItems, itemsToRender } = usePagination(articles);
总结一下问题:每次调用函数时,变量默认始终为 1。因此,当逻辑失败时,它将始终返回 2,例如,在每次单击中,它应该增长 - 1,2,3,4,5 等。getItems
curPage
curPage += 1;
钩子被调用一次,返回的函数被调用多次,但变量包含在自定义钩子函数体中,因此每次函数运行时都应该发生突变。getItems
curPage
我不明白这是怎么回事。我将不胜感激您的建议。提前致谢!马切伊
答:
0赞
Oktay Yuzcan
5/13/2023
#1
它就是 React。它重新渲染东西。这意味着当状态更新时,您的组件(即函数)在每次重新渲染时都会一次又一次地被调用。
- 您定义
curPage = 1
- 然后你递增它
curPage += 1
- 然后,通过以下方式更新状态
setItemsToRender
- 然后你的组件重新渲染(再次执行)
- 再一次
curPage = 1
对此的解决方案是使用 .它保留了渲染之间的更改值(由于闭包)useRef
const curPage = useRef(1)
curPage.current += 1
0赞
PhoenixPan
10/13/2023
#2
正如你所注意到的,这是一个闭包问题,这在 React 钩子中很常见。解决的办法是“打破”闭包,让函数实现改变。curPage
- 正如 Oktay Yuzcan 所指出的,use ,它不是闭包的一部分,因此它可以帮助函数知道闭包之外会发生什么。
useRef()
let curPage = useRef(1);
const getItems = () => {
curPage.current++;
}
- 用于在值更改时更新函数。
useCallback()
curPage
let curPage = 1;
const getItems = useCallback(() => {
curPage++;
}, [curPage]);
对于您的情况,解决方案 1 更好,因为解决方案 2 在每次更改时都会重新创建函数,而解决方案 1 只需要维护一个简单的引用。curPage
避免闭包的另一种方法是将变量移动到内部函数,因此它不是闭包的一部分,而是函数本身的一部分。然而,这并不适合您在这里的情况。
评论
The hook is called once
- 不,每次状态更改或父级重新渲染时,都会调用钩子。