我正在为要在项目(noUiSlider)中使用的外部库创建组件。
目前,我将此作为我的Slider
组件:
function Slider(props) {
const { defaultMin, defaultMax, step } = props;
const sliderElement = useRef();
useEffect(() => {
if (!sliderElement.current) {
return;
}
noUiSlider.create(sliderElement.current, {
connect: true,
start: [defaultMin, defaultMax],
step,
range: {
min: [defaultMin],
max: [defaultMax],
},
});
if (props.onUpdate) {
sliderElement.current.noUiSlider.on('update', props.onUpdate);
}
if (props.onEnd) {
sliderElement.current.noUiSlider.on('end', props.onEnd);
}
}, []);
return <div ref={sliderElement} />;
}
在这里,我等待DOM元素可用,然后在该DOM元素上创建noUiSlider实例(我返回div
)。我还在效果内附加了一些事件处理程序(onUpdate和onEnd)。
Slider
组件的用法如下...
// custom hook that just sets state
const [min, max, setMinMax] = useSlider(10, 300);
const handleEnd = () => {
// these are outdated :(
console.log(min, max);
}
<Slider
defaultMin={10}
defaultMax={300}
step={10}
onEnd={handleEnd}
onUpdate={setMinMax}
/>
我遇到的问题是在handleEnd
内,当我想引用min
和max
时,它们是初始值,而不是我希望更新的值。
如何在同一范围内从我在useEffect
内调用的函数中检索更新的值?
我创建了一个codesandbox示例来展示其实际效果。
答案 0 :(得分:3)
主要问题来自您在useEffect
组件中调用Slider
的方式。您添加了[]
作为第二个参数,这可以防止多次调用您的效果。因此,它仅在第一次渲染后被调用一次,然后再也不会被调用,因此它保留了旧的onEnd
,并保留了过时的最小值和最大值。
来自React's doc:
如果要运行效果并仅将其清理一次(在挂载和卸载时),则可以将空数组([])作为第二个参数传递。这告诉React,您的效果不依赖于道具或状态的任何值,因此它不需要重新运行。
以此代替Slider.js
,它可以起作用:
import React, { useEffect, useRef } from 'react';
import noUiSlider from 'nouislider';
function Slider(props) {
const { defaultMin, defaultMax, step } = props;
const sliderElement = useRef();
useEffect(() => {
noUiSlider.create(sliderElement.current, {
connect: true,
start: [defaultMin, defaultMax],
step,
range: {
min: [defaultMin],
max: [defaultMax],
},
});
if (props.onUpdate) {
sliderElement.current.noUiSlider.on('update', props.onUpdate);
}
}, []);
useEffect(
() => {
if (props.onEnd) {
sliderElement.current.noUiSlider.on('end', props.onEnd);
}
return () => {
sliderElement.current.noUiSlider.off('end');
};
},
[props.onEnd],
);
return <div ref={sliderElement} />;
}
export default Slider;
这里有些话:
props.onChange
从未在Slider
组件中定义或使用。我丢掉了。useEffect
必须分为两个useEffect
:
setMinMax
中的useSlider.js
的有效引用,因此不需要更新)props.onEnd
发生更改时结束事件(实际上是在每个渲染上,请参见index.js > handleEnd
)。 别忘了清理事件监听器。