提问人:workK 提问时间:11/13/2023 最后编辑:ChinezworkK 更新时间:11/15/2023 访问量:31
React useCallback 引用问题和闭包。在渲染时重新创建 UseCallback
React useCallback reference issue and closures . usecallback recreating on renders
问:
import React, { useCallback, useState } from 'react';
const App = () => {
const [count, setCount] = useState(0);
const increase = useCallback(() => {
let count = null;
function incrementByOne() {
count = count + 1;
console.log(count);
}
return incrementByOne;
}, []);
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<button onClick={increase()}>Increase</button>
</>
);
};
export default App;
从上面的代码中,当我单击“增加”按钮(秒)时,计数增加 1 并对其进行控制台化,它不会呈现,但是当我单击第一个按钮时,状态值会发生变化并且组件会呈现。然后当我单击第二个按钮时,计数从 1 开始,即使在使用 useCallback 后,重新渲染后,前一个计数也在初始化为零,重新渲染时的 increase 方法重新创建,谁能解释为什么该值在渲染后没有持久化,并且 useCallback 再次重新创建?
答:
0赞
Bergi
11/13/2023
#1
问题在于没有返回其他函数。当您的组件由于状态更改而重新呈现时,您将再次调用,在新的 .您可以通过添加 ,在上面看到这一点。useCallback
increase()
incrementByOne
count
console.trace('re-initialising count')
increase
let count = null;
要解决此问题,您需要确保在安装组件时仅创建一次闭包,而不是在每次渲染时创建闭包。可以使用 ,但更可靠的解决方案是使用 的初始值设定器功能,只是从不更新状态:useMemo()
useState
function App() {
const [count, setCount] = useState(0);
const [increment, _] = useState(() => {
let count = 0;
return () => {
count = count + 1;
console.log(count);
};
});
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<button onClick={increment}>Increase</button>
</>
);
}
然而,惯用的 React 方法1 将完全避免闭包和可变变量,而是使用 ref:
function App() {
const [count, setCount] = useState(0);
const countRef = useRef(0);
const increment = () => {
countRef.current = countRef.current + 1;
console.log(countRef.current);
};
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<button onClick={increment}>Increase</button>
</>
);
}
1:或者说,你不应该在没有重新渲染的情况下改变任何东西,所以你可以只使用正常状态......
评论
increase()
incrementByOne
count