cbd*_*per 5 javascript reactjs react-hooks
这是我的情况:
我有一个名为的自定义钩子,useClick它获取HTML element和a callback作为输入,将click 事件监听器附加到该钩子,element并将the设置callback为事件处理程序。
App.js
function App() {
const buttonRef = useRef(null);
const [myState, setMyState] = useState(0);
function handleClick() {
if (myState === 3) {
console.log("I will only count until 3...");
return;
}
setMyState(prevState => prevState + 1);
}
useClick(buttonRef, handleClick);
return (
<div>
<button ref={buttonRef}>Update counter</button>
{"Counter value is: " + myState}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
useClick.js
import { useEffect } from "react";
function useClick(element, callback) {
console.log("Inside useClick...");
useEffect(() => {
console.log("Inside useClick useEffect...");
const button = element.current;
if (button !== null) {
console.log("Attaching event handler...");
button.addEventListener("click", callback);
}
return () => {
if (button !== null) {
console.log("Removing event handler...");
button.removeEventListener("click", callback);
}
};
}, [element, callback]);
}
export default useClick;
Run Code Online (Sandbox Code Playgroud)
注意,使用上面的代码,我将在每次调用此钩子时添加和删除事件侦听器。
我非常想仅在安装时添加,在卸除时删除。而不是添加和删除每个呼叫。
即使我正在使用此:
useEffect(()=>{
// Same code as above
},[element,callback]); // ONLY RUN THIS WHEN 'element' OR 'callback' CHANGES
Run Code Online (Sandbox Code Playgroud)
这样做的问题是,即使element(ref)在所有渲染中都保持相同,callback(这是App的handleClick函数)也会在每个渲染中发生变化。所以我最终还是在每个渲染上添加和删除了处理程序。
我也不能转换handleCLick为useCallback,因为它取决于状态myState变量,该状态变量在每个渲染上都会更改,并且useCallback仍然会在每个渲染上(当myState更改时)重新创建我,因此问题仍然存在。
const handleClick = useCallback(()=> {
if (myState === 3) {
console.log("I will only count until 3...");
return;
}
setMyState(prevState => prevState + 1);
},[myState]); // THIS WILL CHANGE ON EVERY RENDER!
Run Code Online (Sandbox Code Playgroud)
题:
我是否应该担心在每个渲染器上都删除并附加监听器?还是这真的完全不贵,有没有伤害我的表现的机会?有没有办法避免呢?
您可以将当前回调存储在 ref 中,并为仅调用当前回调的事件侦听器提供静态回调:
function useClick(element, callback) {
console.log('Inside useClick...');
const callbackRef = useRef(callback);
useEffect(() => {
callbackRef.current = callback;
}, [callback]);
const callbackWrapper = useCallback(props => callbackRef.current(props), []);
useEffect(() => {
console.log('Inside useClick useEffect...');
const button = element.current;
if (button !== null) {
console.log('Attaching event handler...');
button.addEventListener('click', callbackWrapper);
}
return () => {
if (button !== null) {
console.log('Removing event handler...');
button.removeEventListener('click', callbackWrapper);
}
};
}, [element, callbackWrapper]);
}
Run Code Online (Sandbox Code Playgroud)
工作示例:
| 归档时间: |
|
| 查看次数: |
232 次 |
| 最近记录: |