useEffect is not getting call first time when parent state is changed by child state at

244 views Asked by At

Child component

export const FlightRange = (props) => {
  const [value, setValue] = useState(props.value);
  return (
    <>
      <input
        type='range'
        min={1000}
        max={50000}
        step="500"
        value={value}
        onChange={(e) => {
          setValue(e.target.value);
          props.handleSliderChange(value);
        }}
      />
      <span>{value}</span>

    </>
  );
};

parent component

useEffect(() => {
    const result = axios.get('http://localhost:8000/')
    .then((res) => res.json())

    .then((data) => {
      const flightData = data.filter((value) => {
        return (
          valuesplit(' ')[1] < priceSlider
        );
      });
    })
  }, [priceSlider]);

return(
    <Child value={priceSlider} handleSliderChange={(value)=> setPriceSlider(value)} />
 )

useEffect does not get called when the slider is changed the first time. It gets called a second time with the stale (previous value) value. What am I missing?

3

There are 3 answers

5
shubham jha On BEST ANSWER

in onChange you need to call like this

onChange={(e) => {
          setValue(e.target.value);
          props.handleSliderChange(e.target.value);
        }}

since value is not updated instantly when you call setValue(e.target.value); , value will have previous value that you are passing in props.handleSliderChang(value)
to know how setState works see this answer

0
95faf8e76605e973 On

The issue is on the onClick callback of FlightRange input, see comments on code below

onChange = {(e) => {
  setValue(e.target.value); // this is async

  // therefore, the value you are passing here is not the same as e.target.value but simply the value before setting the state
  props.handleSliderChange(value);  
}}

So to fix this just refactor props.handleSliderChange argument to e.target.value

onChange = {(e) => {
  setValue(e.target.value);
  props.handleSliderChange(e.target.value);  
}}
0
aligatr On

It because the child is having it's own life cycle since you are using useState in child. so whatever props you pass to your child, the child's state won't affected.

plus you are passing incorrect value in onChange

Solution: just use the props value directly on child (do not store in state):

export const FlightRange = (props) => {
  const { value, handleSliderChange } = props;
  return (
    <>
      <input
        type='range'
        min={1000}
        max={50000}
        step="500"
        value={value}
        onChange={(e) => {
          handleSliderChange(e.target.value);
        }}
      />
      <span>{value}</span>

    </>
  );
};