Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input range slider as react hook does not slide

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.

like image 522
Richard Michels Avatar asked Sep 17 '19 04:09

Richard Michels


People also ask

How do you make a slider input in React?

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.

When should you not use a hook on a React?

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.


1 Answers

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'))
like image 105
Drew Reese Avatar answered Oct 03 '22 23:10

Drew Reese