Adithya
Adithya

Reputation: 2975

React 'useCallback' for event handler

I have an event handler handleChange which gets called for each drop down (total there are 5) as i have a parent-child component i.e. in the following snippet the drop-down is getting called from a parent and the attributes like label and values are getting populated using props. The issue is as i have a redux store, the components render multiple times and onchange event gets called that many times. To limit the rendering i wanted to use useCallback but the dependency will be based on whether the drop-down value which user selects changes or not. The issue i don't have access to event in the dependency.

import React, {useCallback} from 'react';
import { makeStyles } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';

const useStyles = makeStyles(theme => ({
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120,
  },
  selectEmpty: {
    marginTop: theme.spacing(2),
  },
}));

export default function SimpleSelect(props) {
  const classes = useStyles();
  const [age, setAge] = React.useState('');

  const handleChange = useCallback (event => {
    setAge(event.target.value);
  }, []);

  return (
    <div>
      <FormControl className={classes.formControl}>
        <InputLabel id="demo-simple-select-label">{props.label}</InputLabel>
        <Select
          labelId="demo-simple-select-label"
          id="demo-simple-select"
          value={age}
          onChange={handleChange}
        >
          {props.values}
        </Select>
      </FormControl>
    </div>
  );
}

If i don't put any dependencies as above, then the event is never getting called after user changes the value. It gets called only when initializing and rendering (done by system).

As seen from the codepen link below, the handler is getting called even if i select the same value from the drop-down and to avoid that i need to specify the value inside the drop-down as the dependency,

Link

Upvotes: 1

Views: 11447

Answers (1)

Alex Wayne
Alex Wayne

Reputation: 187222

You've used useCallback correctly. The only real dependency for that callback is setAge which has a function identity that is guaranteed by useState not to change, so this is safe.

The handleChange function can be the same every time the component renders because it doesn't need to do anything different if different values are set. All it needs to do set the name value.

If handleChange is not getting invoked, then the problem is likely in your <Select> component.

Upvotes: 2

Related Questions