为什么在尝试更新状态时使用初始状态

时间:2020-02-06 16:57:13

标签: javascript reactjs react-hooks

我有一个使用钩子表示状态的react组件。我已将home的初始状态设置为{location:null, canCharge: 'yes'}

然后我有几个子组件,它们调用setHome()来更新它们负责的状态。

一个设置location,另一个设置原始状态的canCharge属性。

ChargeRadioGroup的设置器可以正常工作,仅更新canCharge属性,而对location的值没有影响。

然而PlacesAutoComplete集似乎已经捕获了home的初始状态,并且在内部设置了断点后,我看到它总是用home{location:null, canCharge:'yes'}来调用。 >

我意识到我可以将单个状态分为两个单独的状态,一个用于location,一个用于canCharge,但是我想了解为什么会发生这种情况,而不是实施变通方法。 / p>

export default function VerticalLinearStepper() {
  const classes = useStyles();
  const [activeStep, setActiveStep] = React.useState(0);
  const [home, setHome] = useState({
    location: null,
    canCharge: "yes"
  });
  const [work, setWork] = useState({
    location: null,
    canCharge: "yes"
  });
  const steps = getSteps();

  const handleNext = () => {
    setActiveStep(prevActiveStep => prevActiveStep + 1);
  };

  const handleBack = () => {
    setActiveStep(prevActiveStep => prevActiveStep - 1);
  };

  return (
    <div className={classes.root}>
      <Stepper activeStep={activeStep} orientation="vertical">
        <Step>
          <StepLabel>Where do you live?</StepLabel>
          <StepContent>
            <Box className={classes.stepContent}>
              <PlacesAutocomplete
                className={classes.formElement}
                name={"Home"}
                onPlaceSelected={location => setHome({ ...home, location })}
                googleApiKey={"<API_KEY>"}
              />
              <ChargeRadioGroup
                className={classes.formElement}
                label="Can you charge your car here?"
                value={home.canCharge}
                onChange={event =>
                  setHome({ ...home, canCharge: event.target.value })
                }
              />

PlacesAutoComplete组件的代码可以看到here

我猜想这与该组件称为onPlaceSelected道具的方式有关,但是我无法弄清楚到底发生了什么或如何解决:

useEffect(() => {
    if (!loaded) return;
    const config = {
      types,
      bounds,
      fields
    };

    if (componentRestrictions) {
      config.componentRestrictions = componentRestrictions;
    }

    autocomplete = new window.google.maps.places.Autocomplete(
      inputRef.current,
      config
    );

    event = autocomplete.addListener("place_changed", onSelected);
    return () => event && event.remove();
  }, [loaded]);

  const onSelected = () => {
    if (onPlaceSelected && autocomplete) {
      onPlaceSelected(autocomplete.getPlace());
    }
  };

1 个答案:

答案 0 :(得分:1)

更新我的原始答案。

代替此:

onPlaceSelected={location => setHome({ ...home, location })}

此:

onPlaceSelected={newlocation => setHome( (prevState) => (
    { ...prevState, location:newlocation }
    ))}

设置状态函数可以使用值,对象或函数可以接收旧状态并返回新状态。因为设置状态有时是异步的,所以用不同的调用来设置成员的对象状态可能会导致捕获的变量覆盖新状态。

此链接的更多详细信息:https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3