【发布时间】:2022-12-03 15:18:43
【问题描述】:
我是一名学习反应的学生。
我现在制作的组件有问题。
我想做的是一个类似于下面链接的滚动式选择器。
https://codepen.io/gnauhca/pen/JrdpZZ
在这个实现过程中,在eventListener中注册和移除eventListener时出现了问题。
import { useState, useRef, useEffect } from "react";
function Scroller() {
const array = [170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180];
const [dragEventHistory, setDragEventHistory] = useState([]);
const [dragEventStart, setDragEventStart] = useState(null);
const scrollerContainer = useRef();
const scrollerList = useRef();
useEffect(() => {
const moveList = (clientY) => {
const difference = Number(dragEventStart) - Number(clientY);
scrollerList.current.style.transform = `translate3d(0, -${difference}px, 0)`;
};
const onMouseMoveEventHandler = (e) => {
console.log(e);
e.preventDefault();
moveList(e.clientY);
};
const onMouseDownEventHandler = (e) => {
console.log(e);
e.preventDefault();
setDragEventStart(e.clientY);
scrollerContainer.current.addEventListener(
"mousemove",
onMouseMoveEventHandler
);
};
const onMouseUpEventHandler = (e) => {
console.log(e);
e.preventDefault();
scrollerContainer.current.removeEventListener(
"mousemove",
onMouseMoveEventHandler
);
};
scrollerContainer.current.addEventListener(
"mousedown",
onMouseDownEventHandler
);
scrollerContainer.current.addEventListener(
"mouseup",
onMouseUpEventHandler
);
return () => {
scrollerContainer.current.removeEventListener(
"mousedown",
onMouseDownEventHandler
);
scrollerContainer.current.removeEventListener(
"mouseup",
onMouseUpEventHandler
);
};
}, []);
return (
<div
className="scroller-container"
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
width: 200,
height: 250,
}}
ref={scrollerContainer}
// onTouchStart={onTouchStartEventHandler}
// onTouchEnd={onTouchEndEventHandler}
>
<ul className="scroller-list" ref={scrollerList}>
{array.map((item, index) => {
return (
<li
key={index}
style={{
width: 200,
height: 50,
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: "orange",
fontSize: 30,
}}
>
{item}
</li>
);
})}
</ul>
</div>
);
}
export default Scroller;
如果我不使用 useEffect 定义函数,根据 'dragEventStart' 状态的变化,注册为事件的回调函数无法在组件重新渲染过程中删除。
如果我在useEffect中定义函数,removeEventListener函数可以指向与addEventListener函数的回调相同的回调函数。但无法更改 dragEventStart 状态。但是,如果 dragEventStart 包含在 useEffect 的依赖项中,则与不使用 useEffect 时相同。
我怎么解决这个问题?我需要帮助!!
【问题讨论】:
-
为什么你会在 React 中使用
addEventListener而不是为此设计的道具? -
@KonradLinkowski 你好! onMouseDown 和 onMouseUp 可以通过 react 道具注册,但我真正的问题是 onMouseMove 事件!如果 onMouseDown 为 ON,则应注册 onMouseMove 事件,如果 onMouseUp 为 ON,则应将其删除。 onMouseMove 事件的回调函数有一个状态(dragEventStart),所以问题出现了!
标签: javascript reactjs react-hooks