Почему используется исходное состояние при попытке обновить состояние - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть компонент реагирования, который использует хуки для состояния. Я установил начальное состояние для home равным {location:null, canCharge: 'yes'}.

Затем у меня есть пара подкомпонентов, которые вызывают setHome() для обновления частей состояния, за которое они отвечают.

Один устанавливает location, а другой устанавливает свойство canCharge домашнего состояния.

Установщик для ChargeRadioGroup работает, как ожидается, только обновляет свойство canCharge и не имеет никакого эффекта на значение location.

Однако набор PlacesAutoComplete, похоже, захватил начальное состояние дома, и после установки точки останова внутри я вижу, что он всегда вызывается с home: {location:null, canCharge:'yes'}.

Я понимаю, что могу разбить это единственное состояние на два отдельных состояния, одно для location и одно для canCharge, но я хотел бы понять, почему это происходит вместо реализации обходного пути .

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 можно увидеть здесь

Я предполагаю, что это как-то связано с тем, как этот компонент вызывает это 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 Ответ

1 голос
/ 06 февраля 2020

Обновление моего исходного ответа.

Вместо этого:

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

Это:

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

Установленные функции состояния могут принимать значение, и объект или функция, которая получает старое состояние и возвращает новое состояние. Поскольку состояние установки иногда является асинхронным, состояние объекта, члены которого устанавливаются с различными вызовами, может привести к тому, что захваченные переменные перезаписывают новое состояние.

Подробнее по этой ссылке: https://medium.com/@wereHamster / beware-реагировать-setstate- является асинхронным-ce87ef1a9cf3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...