I am trying to make a basic input range slider component using React hooks. However, sliding the actual value knob does not work. Only clicking directly on a new value location on the slide track changes the value.
Example codepen: https://codepen.io/rmichels/pen/WNegjyK
this is my current component code, which the above codepen reproduces:
import React, { useState } from "react";
const useSlider = (min, max, defaultState, label, id) => {
const [state, setSlide] = useState(defaultState);
const handleChange = e => {
setSlide(e.target.value);
};
const Slider = () => (
<input
type="range"
id={id}
min={min}
max={max}
step={10}
value={state}
onChange={handleChange}
/>
);
return [state, Slider, setSlide];
};
export default useSlider;
I want to click on the knob and slide it left and right, firing the onChange
function and triggering setState
on the value as it's changed.
Approach: To add our slider input we are going to use the react-input-slider package. The react-input-slider package helps us to integrate the slider input in our app. So first, we will install the react-input-slider package and then we will add a slider input on our homepage. Project Structure: It will look like this.
1. Changing the Hooks Invocation Order. Hooks should not be called within loops, conditions, or nested functions since conditionally executed Hooks can cause unexpected bugs. Avoiding such situations ensures that Hooks are called in the correct order each time the component renders.
Your component is setting state on each update of the slider, so the component is re-rendering and you lose focus or hold of the slider handle. Instead, you should update state when the interaction with the handle is complete.
//import { useState } from 'react';
const { useState } = React;
const useSlider = (min, max, defaultState, label, id) => {
const [state, setSlide] = useState(defaultState);
const handleChange = e => {
console.log('setting level', e.target.value)
setSlide(e.target.value);
};
const Slider = () => (
<input
type="range"
id={id}
min={min}
max={max}
step={0.5}
// value={state} // don't set value from state
defaultValue={state} // but instead pass state value as default value
onChange={e => console.log(e.target.value)} // don't set state on all change as react will re-render
onMouseUp={handleChange} // only set state when handle is released
/>
);
return [state, Slider, setSlide];
};
const App = () => {
const [slideValue, Slider] = useSlider(
1,
100,
70,
"Threshold",
"threshold"
);
return (
<div>
<Slider />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('app'))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With