Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A component is changing the default value state of an uncontrolled Slider after being initialized. Material UI Slider with Redux State

I am trying to run a redux action that fetches a db and store it in a state variable. I am then using this variable as a default for a Material UI Slider. I am initializing this default value (to avoid being null which usually solves the problem) and then using useState to set the value when the fetch is complete. I cant get rid of the warning A component is changing the default value state of an uncontrolled Slider after being initialized. although my slider value is never set to Null Below is my page code and reducer Page:

import React, { useState, useEffect } from 'react';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Typography from '@material-ui/core/Typography';
import Slider from '@material-ui/core/Slider';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { getSettings } from '../../actions/settingsActions';

const Settings = ({ getSettings, settings }) => {
  React.useEffect(() => {
    getSettings();

    // eslint-disable-next-line
  }, []);

  const [current, setCurrent] = useState({
    ageAtDeath: 50,
  });

  React.useEffect(() => {
    if (settings.ageAtDeath) {
      //only loads when settings is not null as set in initial state getSettings() completed!
      setCurrent({
        ageAtDeath: settings.ageAtDeath,
      });
    }
  }, [settings]);

  return (
    <Card>
      <CardContent>
        <Typography color='textSecondary' gutterBottom>
          Age at death:
        </Typography>
        <Slider
          defaultValue={current.ageAtDeath}
          aria-labelledby='discrete-slider'
          valueLabelDisplay='auto'
          step={10}
          marks
          min={10}
          max={110}
        />
      </CardContent>
    </Card>
  );
};

Settings.propTypes = {
  getSettings: PropTypes.func.isRequired,
  settings: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  settings: state.settings.settings,
});

export default connect(mapStateToProps, {
  getSettings,
})(Settings);

Reducer Code:

import {
  GET_SETTINGS,
 
} from '../actions/Types';

const initialState = {
  settings: {ageAtDeath: 0},

};

export default (state = initialState, action) => {
  switch (action.type) {
    case GET_SETTINGS:
      return {
        ...state,
        settings: action.payload,
        
      };
    default:
      return state;
  }
};
like image 527
Mohamed Daher Avatar asked Nov 30 '22 13:11

Mohamed Daher


2 Answers

I solved this issue by adding key to component

<Slider
    key={`slider-${currentConcurrency}`} /* fixed issue */
    defaultValue={currentConcurrency}
    step={1}
    max={maxConcurrency}
    min={1}
    marks
    valueLabelDisplay={'auto'}
    onChangeCommitted={this.handleSliderChange('currentConcurrency')} /* increase render performance */
/>
like image 167
Cong Dan Luong Avatar answered Dec 04 '22 01:12

Cong Dan Luong


⚠️ You should use value attribute instead of defaultValue⚠️

  <Slider
      value={current.ageAtDeath} /*defaultValue={current.ageAtDeath}*/
      aria-labelledby='discrete-slider'
      valueLabelDisplay='auto'
      step={10}
      marks
      min={10}
      max={110}
    />
like image 20
Nguyễn Văn Phong Avatar answered Dec 04 '22 03:12

Nguyễn Văn Phong