React Material-UI slider value keeps resetting to zero

Viewed 1222

I am building an interface where you choose a radio and it will reveal different form elements.

When a slider is revealed the value change gets set into an object that is rendered on the page.

In this example I have it so it does update the object but the slider no longer moves even though the value is getting correctly set if you click on the line.

https://codesandbox.io/s/shy-dawn-e5zyu

The object I am setting is declared in the parent :

  const defaultActivity = {
    group: "",
    a: 0,
    b: 0
  };

  const [activity, setActivity] = useState(defaultActivity);

Then in the child component that contains the slider the handleChange function is use within that component and I also use a parent function to access setActivity.

const TestSlider = (props) => {
  const [value, setValue] = React.useState(0);
  const handleChange = (event, newValue) => {
    setValue(newValue);

// This sets the slider value to the activity object
// if you comment this line out then the sliders slide correctly

props.onDataChanged(props.name.toLowerCase(), newValue);

  };
  return (
    <React.Fragment>
      <Typography id="discrete-slider" gutterBottom>
        {props.name}
      </Typography>
      <Slider
        value={value}
        aria-labelledby="discrete-slider"
        valueLabelDisplay="auto"
        step={props.step}
        marks
        min={0}
        max={props.max}
        name={props.name}
        onChange={handleChange}
      />
    </React.Fragment>
  );
};

And that onDataChanged method in the parent


  const onDataChanged = (name, value) => {
    setActivity({
      ...activity,
      [name]: value
    });
  };

As I noted in the comment there, if you remove the onDataChanged method then the sliders work again. I have tried moving handleChange to the parent as well but that did not help.

After creating this Sandbox I seem to have a new problem that is sporadic and unclear to me steps to replicate where I am getting the error : Cannot read property 'getBoundingClientRect' of null

Maybe related to broken slider issue or something else I screwed up. Thanks in advance for any help with this, I am trying hard to learn my way around React but this problem has me really stumped.

============= UPDATE: Closer to expected and a new problem =============

Still playing with this and decided to try and use onChangeCommitted on the slider to try and disconnect the value getting set in the slider with it getting set to the main object. Now it slides and updates the value which sticks in the object but gets reset to 0 for the slider UI. Hard to explain so maybe easier if you go play with it and see what I mean. I think the way I am setting the default state is probably the issue but not sure how to refactor this :

https://codesandbox.io/s/sleepy-euler-0dv69?file=/src/TestSlider.js:116-163

1 Answers

The root of the problem is that the component RenderSwitch is created (declared) inside the AddActivitySelect (SelectForm) component. Moving RenderSwitch outside and passing all necessary props fixes the problem. Here is a working codesandbox.

What happened:

  • When you call props.setActivity in TestSlider, the activity state updates in App
  • App re-renders which causes SelectForm to re-render also.
  • Because a completely new RenderSwitch component is created inside SelectForm, the previous one in unmounted (destroyed).
  • The new RenderSwitch is rendered, calls React.useState(0), and that's why the slider value is 0
Related