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)
请注意,使用上面的代码,我将在此钩子的每次调用中添加和删除事件侦听器(因为回调函数which is handleClick会在每个渲染器上进行更改)。而且必须更改,因为它取决于myState变量,所以每个渲染都必须更改。
我非常想仅在装入时添加事件侦听器,在卸除时删除事件侦听器。而不是添加和删除每个呼叫。
在这里,有人建议我可以使用以下内容:
useClick.js
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)
题
它按预期工作。它仅在装入时添加事件监听器,而在卸除时将其删除。
上面的代码使用了一个回调包装,该包装使用的ref将在渲染器之间保持不变(因此我可以将其用作事件处理程序,并且只能将其安装一次),并且其.current属性将通过useEffect钩子在每个渲染器上使用新的回调进行更新。。
问题是:从性能角度考虑,哪种方法最好?运行useEffect()钩子是否比在每个渲染器上添加和删除事件侦听器便宜?
反正我可以测试一下吗?
小智 1
应用程序.js
function App() {
const buttonRef = useRef(null);
const [myState, setMyState] = useState(0);
// handleClick remains unchanged
const handleClick = useCallback(
() => setMyState(prevState => prevState >= 3 ? 3 : prevState + 1),
[]
);
useClick(buttonRef, handleClick);
return (
<div>
<button ref={buttonRef}>Update counter</button>
{"Counter value is: " + myState}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
更专业的回答:
应用程序.js
function App() {
const buttonRef = useRef(null);
const [myState, handleClick] = useReducer(
prevState => prevState >= 3 ? 3 : prevState + 1,
0
);
useClick(buttonRef, handleClick);
return (
<div>
<button ref={buttonRef}>Update counter</button>
{"Counter value is: " + myState}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
109 次 |
| 最近记录: |