"useRefs" 变量的初始值 div 引用?
"useRefs" variable an initial value of a div reference?
我正在尝试使用 React Hook 构建一个音频进度条。我正在学习基于 React class 的组件的教程,但对 refs 有点迷茫。
如何在页面加载时为 useRef 变量提供 div ref 的初始值?
我一开始玩就收到一条错误消息,说无法读取 null 的 offsetwidth。显然 timeline ref 为空,因为它没有初始值。如何将它连接到 useEffect 挂钩中具有时间线 ID 的 div?
const AudioPlayer = () => {
const url = "audio file";
const [audio] = useState(new Audio(url));
const [duration, setDuration] = useState(0);
const [currentTime, setCurrentTime] = useState(0)
let timelineRef = useRef()
let handleRef = useRef()
useEffect(() => {
audio.addEventListener('timeupdate', e => {
setDuration(e.target.duration);
setCurrentTime(e.target.currentTime)
let ratio = audio.currentTime / audio.duration;
let position = timelineRef.offsetWidth * ratio;
positionHandle(position);
})
}, [audio, setCurrentTime, setDuration]);
const mouseMove = (e) => {
positionHandle(e.pageX);
audio.currentTime = (e.pageX / timelineRef.offsetWidth) * audio.duration;
};
const mouseDown = (e) => {
window.addEventListener('mousemove', mouseMove);
window.addEventListener('mouseup', mouseUp);
};
const mouseUp = (e) => {
window.removeEventListener('mousemove', mouseMove);
window.removeEventListener('mouseup', mouseUp);
};
const positionHandle = (position) => {
let timelineWidth = timelineRef.offsetWidth - handleRef.offsetWidth;
let handleLeft = position - timelineRef.offsetLeft;
if (handleLeft >= 0 && handleLeft <= timelineWidth) {
handleRef.style.marginLeft = handleLeft + "px";
}
if (handleLeft < 0) {
handleRef.style.marginLeft = "0px";
}
if (handleLeft > timelineWidth) {
handleRef.style.marginLeft = timelineWidth + "px";
}
};
return (
<div>
<div id="timeline" ref={(timeline) => { timelineRef = timeline }}>
<div id="handle" onMouseDown={mouseDown} ref={(handle) => { handleRef = handle }} />
</div>
</div>
)
}
useRef()
hook returns 对象的引用,用 current
属性。 current
属性 是 useRef
指向的实际值。
要使用引用,只需在元素上设置它:
<div id="timeline" ref={timelineRef}>
<div id="handle" onMouseDown={mouseDown} ref={handleRef} />
然后使用需要参考current
属性:
let position = current.timelineRef.offsetWidth * ratio;
和 positionHandle
- 你实际上不应该以这种方式在 React 中的元素上设置样式。使用 setState()
钩子,并使用 JSX 设置样式。
const positionHandle = (position) => {
let timelineWidth = timelineRef.current.offsetWidth - handleRef.current.offsetWidth;
let handleLeft = position - timelineRef.current.offsetLeft;
if (handleLeft >= 0 && handleLeft <= timelineWidth) {
handleRef.current.style.marginLeft = handleLeft + "px";
}
if (handleLeft < 0) {
handleRef.current.style.marginLeft = "0px";
}
if (handleLeft > timelineWidth) {
handleRef.current.style.marginLeft = timelineWidth + "px";
}
};
此外,ref还可以用于其他值,例如new Audio(url)
,并从current
中提取属性:
const { current: audio } = useRef(new Audio(url));
我正在尝试使用 React Hook 构建一个音频进度条。我正在学习基于 React class 的组件的教程,但对 refs 有点迷茫。
如何在页面加载时为 useRef 变量提供 div ref 的初始值?
我一开始玩就收到一条错误消息,说无法读取 null 的 offsetwidth。显然 timeline ref 为空,因为它没有初始值。如何将它连接到 useEffect 挂钩中具有时间线 ID 的 div?
const AudioPlayer = () => {
const url = "audio file";
const [audio] = useState(new Audio(url));
const [duration, setDuration] = useState(0);
const [currentTime, setCurrentTime] = useState(0)
let timelineRef = useRef()
let handleRef = useRef()
useEffect(() => {
audio.addEventListener('timeupdate', e => {
setDuration(e.target.duration);
setCurrentTime(e.target.currentTime)
let ratio = audio.currentTime / audio.duration;
let position = timelineRef.offsetWidth * ratio;
positionHandle(position);
})
}, [audio, setCurrentTime, setDuration]);
const mouseMove = (e) => {
positionHandle(e.pageX);
audio.currentTime = (e.pageX / timelineRef.offsetWidth) * audio.duration;
};
const mouseDown = (e) => {
window.addEventListener('mousemove', mouseMove);
window.addEventListener('mouseup', mouseUp);
};
const mouseUp = (e) => {
window.removeEventListener('mousemove', mouseMove);
window.removeEventListener('mouseup', mouseUp);
};
const positionHandle = (position) => {
let timelineWidth = timelineRef.offsetWidth - handleRef.offsetWidth;
let handleLeft = position - timelineRef.offsetLeft;
if (handleLeft >= 0 && handleLeft <= timelineWidth) {
handleRef.style.marginLeft = handleLeft + "px";
}
if (handleLeft < 0) {
handleRef.style.marginLeft = "0px";
}
if (handleLeft > timelineWidth) {
handleRef.style.marginLeft = timelineWidth + "px";
}
};
return (
<div>
<div id="timeline" ref={(timeline) => { timelineRef = timeline }}>
<div id="handle" onMouseDown={mouseDown} ref={(handle) => { handleRef = handle }} />
</div>
</div>
)
}
useRef()
hook returns 对象的引用,用 current
属性。 current
属性 是 useRef
指向的实际值。
要使用引用,只需在元素上设置它:
<div id="timeline" ref={timelineRef}>
<div id="handle" onMouseDown={mouseDown} ref={handleRef} />
然后使用需要参考current
属性:
let position = current.timelineRef.offsetWidth * ratio;
和 positionHandle
- 你实际上不应该以这种方式在 React 中的元素上设置样式。使用 setState()
钩子,并使用 JSX 设置样式。
const positionHandle = (position) => {
let timelineWidth = timelineRef.current.offsetWidth - handleRef.current.offsetWidth;
let handleLeft = position - timelineRef.current.offsetLeft;
if (handleLeft >= 0 && handleLeft <= timelineWidth) {
handleRef.current.style.marginLeft = handleLeft + "px";
}
if (handleLeft < 0) {
handleRef.current.style.marginLeft = "0px";
}
if (handleLeft > timelineWidth) {
handleRef.current.style.marginLeft = timelineWidth + "px";
}
};
此外,ref还可以用于其他值,例如new Audio(url)
,并从current
中提取属性:
const { current: audio } = useRef(new Audio(url));