以表单形式提交时我无法更新状态

I can't update state when submitted in a form

我需要更新主页上的状态,问题是我将值更新向下 3 级...

这个组件是我获取所有城市的地方,将数据放在州和城市地图上。

CitiesPage.tsx

export const CitiesPage = () => {
  const [cities, setCities] = useState<City[]>([]);

  useEffect(() => {
    getCities().then(setCities);
  }, []);

  return (
    <>
      <PageTitle title="Cities" />
      <StyledCitySection>
        <div className="headings">
          <p>Name</p>
          <p>Iso Code</p>
          <p>Country</p>
          <span style={{ width: "50px" }}></span>
        </div>
        <div className="cities">
          {cities.map((city) => {
            return <CityCard key={city.id} city={city} />;
          })}
        </div>
      </StyledCitySection>
    </>
  );
};

在下一个组件中,我将显示城市和选项以显示删除和更新模式。

CityCard.tsx.

export const CityCard = ({ city }: CityProps) => {
  const [showModal, setShowModal] = useState(false);

  const handleModal = () => {
    setShowModal(true);
  };

  const handleClose = () => {
    setShowModal(false);
  };

  return (
    <>
      {showModal && (
        <ModalPortal onClose={handleClose}>
          <EditCityForm city={city} closeModal={setShowModal} />
        </ModalPortal>
      )}
      <StyledCityCard>
        <p className="name">{city.name}</p>
        <p className="isoCode">{city.isoCode}</p>
        <p className="country">{city.country?.name}</p>
        <div className="options">
          <span className="edit">
            <FiEdit size={18} onClick={handleModal} />
          </span>
          <span className="delete">
            <AiOutlineDelete size={20} />
          </span>
        </div>
      </StyledCityCard>
    </>
  );
};

最后,向下三层,我有这个组件。

EditCityForm.tsx.

export const EditCityForm = ({ city, closeModal }: Props) => {
  const [updateCity, setUpdateCity] = useState<UpdateCity>({
    countryId: "",
    isoCode: "",
    name: "",
  });

  const handleChange = (
    evt: ChangeEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    const { target } = evt;
    setUpdateCity({ ...updateCity, [target.name]: target.value });
  };

  const handleSubmit = (evt: FormEvent<HTMLFormElement>) => {
    evt.preventDefault();
    const { id: cityId } = city;
    updateCityHelper(cityId, updateCity);
    closeModal(false);
  };

  useEffect(() => {
    setUpdateCity({
      isoCode: city.isoCode,
      name: city.name,
      countryId: city.country?.id,
    });
  }, [city]);

  return (
    <form onSubmit={handleSubmit}>
      <Input
        label="Iso Code"
        type="text"
        placeholder="Type a IsoCode..."
        onChange={handleChange}
        name="isoCode"
        value={updateCity.isoCode}
      />
      <Input
        label="Name"
        type="text"
        placeholder="Paste a Name.."
        onChange={handleChange}
        name="name"
        value={updateCity.name}
      />
      <CountrySelect
        label="Country"
        onChange={handleChange}
        value={city.country?.name || ""}
        name="countryId"
      />
      <Button type="submit" color="green" text="Update" />
    </form>
  );
};

编辑表单,检索从 CityCard.tsx 传递的数据并更新状态,将数据传递给更新信息的函数,关闭模态和...这是我的地方不知道怎么办。

当我在 EditCityForm.tsx[=13 上提交时,如何显示在 CitiesPage.tsx 上更新的信息=]

任何帮助将不胜感激。
谢谢!

我建议您使用 React-Redux 或 Context API 每当您有嵌套结构并希望在整个应用程序中访问数据时。

但是在这种情况下,您可以将 setCitiescities 作为道具传递给 CityCard,然后在 EditCityForm 组件中传递相同的道具,您可以这样做在你的 handleSubmit 中有这样的东西。

const handleSubmit = (evt: FormEvent<HTMLFormElement>) => {
    evt.preventDefault();
    let updatedCities = [...cities];
    updatedCities.forEach(el => {
       if(el.id == updateCity.id) {
         el.countryCode = updateCity.countryCode;
         el.name = updateCity.name;
         el.isoCode = updateCity.isoCode;
       }
    })
    setCities(updatedCities);
    closeModal(false);
  };

您正在将更新后的值存储在不同的状态,即 updateCity 状态,但您应该做的是更新原始 cities 状态。虽然这两个状态不相关,同时你的 UI 依赖于 cities 状态的数据,所以如果你想更新 UI,你需要做的是更新 cities' 使用它的 setter 函数 setCities.

的状态

就像向下传递状态一样,您也传递它的 setters,并使用 setter 函数更新状态的值:

// CitiesPage
{cities.map((city) => {
    return <CityCard key={city.id} city={city} setCities={setCities} />;
})}

// CityCard
export const CityCard = ({ city, setCities }: CityProps) => {
    // ...

    return (
        // ...
        <ModalPortal onClose={handleClose}>
          <EditCityForm city={city} closeModal={setShowModal} setCities={setCities} />
        </ModalPortal>
        // ...
    )
}


// EditCityForm
export const EditCityForm = ({ city, closeModal, setCities }: Props) => {
  // const [updateCity, setUpdateCity] = useState<UpdateCity>({  // no need for this
  //   countryId: "",
  //   isoCode: "",
  //   name: "",
  // });  

  const handleSubmit = (evt: FormEvent<HTMLFormElement>) => {
    evt.preventDefault();
    const { id: cityId } = city;
    setCities(); // your update logic
    closeModal(false);
  };
}