0

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?

sagar735
  • 43
  • 1
  • 6

3 Answers3

2

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

shubham jha
  • 1,410
  • 12
  • 19
  • What if I have multiple form elements in a child element. Whenever each element change how can I trigger the parent element in the same render cycle `const [journeyInfo, setJourneyInfo] = useState({ source: props.journeyInfo.source } setJourneyInfo({ ...journeyInfo, source: e.target.value }) } /> – sagar735 Sep 27 '20 at 06:44
  • instead of creating states in child and parent just create state in parent and pass down to child and `onChange` update the state of parent, here i can see you have created `value` and `priceSlider` , you can use `priceSlider` in child as well, no need to create same state in child – shubham jha Sep 27 '20 at 06:48
  • like the following – shubham jha Sep 27 '20 at 06:52
  • `const [value, setValue] = props.value`; – shubham jha Sep 27 '20 at 06:53
1

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);  
}}
95faf8e76605e973
  • 13,643
  • 3
  • 24
  • 51
0

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>

    </>
  );
};
aligatr
  • 113
  • 6