【问题标题】:useEffect is not getting call first time when parent state is changed by child state at当父状态被子状态更改时,useEffect 没有第一次被调用
【发布时间】:2021-01-13 01:09:48
【问题描述】:

子组件

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>

    </>
  );
};

父组件

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。它被第二次调用,并带有陈旧的(以前的值)值。 我错过了什么?

【问题讨论】:

    标签: javascript reactjs react-hooks use-effect


    【解决方案1】:

    onChange你需要这样调用

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

    因为当您调用 setValue(e.target.value); 时值不会立即更新,value 将具有您在 props.handleSliderChang(value) 中传递的先前值
    要了解setState 的工作原理,请参阅此answer

    【讨论】:

    • 如果我在一个子元素中有多个表单元素怎么办。每当每个元素发生变化时,我如何在同一个渲染周期中触发父元素const [journeyInfo, setJourneyInfo] = useState({ source: props.journeyInfo.source } &lt;Input type='text' value={journeyInfo.source} onChange={(e) =&gt; setJourneyInfo({ ...journeyInfo, source: e.target.value }) } /&gt; &lt;Button onClick={(e) =&gt; { e.preventDefault(); props.handleFormInfo(journeyInfo); }}&gt;
    • 不是在子节点和父节点中创建状态,而是在父节点中创建状态并传递给子节点,onChange 更新父节点的状态,在这里我可以看到您已经创建了 valuepriceSlider ,你也可以在child中使用priceSlider,不需要在child中创建相同的状态
    • 像下面这样
    • &lt;Child value={[priceSlider,setPriceSlider]} /&gt;
    • const [value, setValue] = props.value;
    【解决方案2】:

    问题出在FlightRange inputonClick 回调上,请参阅下面代码中的cmets

    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);  
    }}
    

    所以要解决这个问题,只需将 props.handleSliderChange 参数重构为 e.target.value

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

    【讨论】:

      【解决方案3】:

      这是因为孩子有自己的生命周期,因为您在孩子中使用useState。所以无论你传递给孩子什么道具,孩子的状态都不会受到影响。

      另外,您在 onChange 中传递的值不正确

      解决方案:直接在child上使用props值(不要存储在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>
      
          </>
        );
      };
      

      【讨论】:

        猜你喜欢
        • 2012-06-01
        • 2019-03-26
        • 2021-06-08
        • 2021-06-27
        • 2014-05-22
        • 2020-07-17
        • 1970-01-01
        • 2019-12-12
        相关资源
        最近更新 更多