簡體   English   中英

按需更新 React 輸入字段值

[英]Update React input fields values on demand

我正在嘗試在 React 中實現一個兩頁的表單。 在第一頁上,我請求了一個代碼,用於獲取需要在第二頁上顯示的一些數據。 在這里,我所說的頁面是指同一頁面上的不同視圖。 我面臨的問題是,當我收到來自后端 API 的響應時,我使用 state 更新當前的 state 字段,而這似乎不會立即發生。 當我更改決定要呈現哪個視圖的屬性的值時,這些字段仍然是空的,不會使用從 API 獲取的值進行更新。 現在,我知道 setState 是異步的,但我不知道如何處理這種情況,因為數據獲取是按需完成的,而不是一開始就完成,所以我認為我不能使用 useEffect 來完成這項工作。

這是我的 state:

  const [state, setState] = useState({
    name: "",
    cif: "",
    address: "",
    phone: "",
    fax: "",
    managerName: "",
    email: "",
    password: "",
  });
  const [companyDataFetched, setCompanyDataFetched] = useState(false);

這是兩個視圖以及我如何在它們之間切換:

{!companyDataFetched ? (
              <CustomForm layout={theme.layout} widthelem={"70%"}>
                <Form.Item
                  name="Company CIF:"
                  label="Company CIF:"
                  rules={[
                    {
                      pattern: new RegExp(/^\d{2,10}$/),
                      message: "Invalid CIF!",
                    },
                    {
                      required: true,
                      message: "Please insert the CIF of the company!",
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "cif")}
                  />
                </Form.Item>
                <CustomButton
                  backgroundcolor={theme.primaryColor}
                  textcolor={theme.white}
                  onClick={() => {
                    axios.get(`${process.env.REACT_APP_API_URL}/Company/GetByCUI/${state.cif}`)
                      .then((res) => {
                        const companyInfo = res.data;

                        if (companyInfo.name) {
                          setState((prevState) => {
                            return {
                              ...prevState,
                              name: companyInfo.name
                            };
                          });
                        }

                        if (companyInfo.address) {
                          setState((prevState) => {
                            return {
                              ...prevState,
                              "address": companyInfo.address,
                            };
                          });
                        }

                        if (companyInfo.phone) {
                          setState((prevState) => {
                            return {
                              ...prevState,
                              "phone": companyInfo.phone,
                            };
                          });
                        }

                        if (companyInfo.fax) {
                          setState((prevState) => {
                            return {
                              ...prevState,
                              "fax": companyInfo.fax,
                            };
                          });
                        }

                        setCompanyDataFetched(true);
                      })
                      .catch((error) => {
                        console.log(error);
                      });
                  }}
                  margintop={"13%"}
                  marginbottom={"13%"}
                >
                  Continue
                </CustomButton>
              </CustomForm>
            ) : (
              <CustomForm layout={theme.layout} widthelem={"70%"}>
                <Form.Item
                  name="Company name:"
                  label="Company name:"
                  rules={[
                    {
                      required: true,
                      message: "Please insert the name of the company!",
                      whitespace: true,
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "name")}
                    value={state.name}
                  />
                </Form.Item>
                <Form.Item
                  name="Company CIF:"
                  label="Company CIF:"
                  rules={[
                    {
                      pattern: new RegExp(/^\d{2,10}$/),
                      message: "Invalid CIF!",
                    },
                    {
                      required: true,
                      message: "Please insert the CIF of the company!",
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "cif")}
                    value={state.cif}
                    disabled={true}
                  />
                </Form.Item>
                <Form.Item
                  name="Address:"
                  label="Address:"
                  rules={[
                    {
                      required: true,
                      message: "Please insert the address of the company!",
                      whitespace: true,
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "address")}
                    value={state.address}
                  />
                </Form.Item>
                <Form.Item
                  name="Phone:"
                  label="Phone:"
                  rules={[
                    {
                      required: true,
                      message:
                        "Please insert the phone number of the company!",
                      whitespace: true,
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "phone")}
                    value={state.phone}
                  />
                </Form.Item>
                <Form.Item
                  name="Fax:"
                  label="Fax:"
                  rules={[
                    {
                      required: true,
                      message: "Please insert the fax of the company!",
                      whitespace: true,
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "fax")}
                    value={state.fax}
                  />
                </Form.Item>
                <Form.Item
                  name="Manager name:"
                  label="Manager name:"
                  rules={[
                    {
                      required: true,
                      message:
                        "Please, insert the name of the company manager!",
                      whitespace: true,
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) =>
                      handleChange(event, "managerName")
                    }
                  />
                </Form.Item>
                <Form.Item
                  name="Manager e-mail:"
                  label="Manager e-mail:"
                  rules={[
                    {
                      type: "email",
                      message: "Invalid e-mail!",
                    },
                    {
                      required: true,
                      message:
                        "Please insert the e-mail of the company manager!",
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "email")}
                  />
                </Form.Item>
                <Form.Item
                  name="Password:"
                  label="Password:"
                  rules={[
                    {
                      required: true,
                      message: "Please, insert a password!",
                    },
                    {
                      min: 4,
                      message: "Password needs to be at least 4 characters long",
                    },
                  ]}
                >
                  <CustomInput
                    backgroundcolor={theme.white}
                    onChange={(event) => handleChange(event, "password")}
                    type={"password"}
                    onKeyPress={verifyCredentials}
                  />
                </Form.Item>
                <CustomButton
                  backgroundcolor={theme.primaryColor}
                  textcolor={theme.white}
                  onClick={() => {
                    signup();
                  }}
                  margintop={"13%"}
                  marginbottom={"13%"}
                >
                  Register
                </CustomButton>
              </CustomForm>
            )}

主要問題是當 companyDataFetched 變為真時,包含字段值的 state 不會更新,並且字段的值不會隨着從后端獲取的數據而更新。 我該如何處理這個問題?

[派曼建議后的更新]

我嘗試使用 useEffect 和另一個 state 作為 API 響應,但結果是一樣的。

這是我更新的代碼:

  useEffect(() => {
    if (companyDataFetched) {
      console.log(response);

      setState((prevState) => {
        return {
          ...prevState,
          nume: response.name,
          adresa: response.address,
          telefon: response.phone,
          fax: response.fax
        }
      });
    }
  }, [companyDataFetched, response]);
axios.get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`)
     .then((res) => {
       setResponse(res.data);
       setCompanyDataFetched(true);
     })
     .catch((error) => {
       console.log(error);
     });

[桑吉特建議后的更新]

我嘗試使用您的建議。 它沒有直接工作,所以我做了一些更改,但它還沒有工作。

這是我更新的代碼:

useEffect(() => {
    const fetchData = () => {
        return axios
           .get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`)
           .then((res) => {
               return res;
           })
           .catch((error) => {
               console.log(error);
           });
    };

    let isMounted = true;
 
    if (companyDataFetched) {
        (async () => {
            const response = await fetchData();

            if (isMounted) {
                setState((prevState) => {
                    return {
                        ...prevState,
                        name: response.data.name,
                        address: response.data.address,
                        phone: response.data.phone,
                        fax: response.data.fax,
                    };
                });
            } else {
                setCompanyDataFetched(false);
            }
        })();
    }
  
    return function () {
        isMounted = false;
    };
}, [companyDataFetched, state.cif]);

You should set your state in useEffect when companyDataFetched changed to true and also one state to save response data from api, so in onClick Function. 您應該保存對另一個 state 的響應並將 setCompanyDataFetched 設置為 true 以運行 useEffect 然后在 useEffect 中更改狀態值。

const [response , setResponse] = useState(null);
useEffect(() => {
  if(companyDataFetched){
       setState({
        fax : response.fax,
        phone : response.phone,
        .........
       })
  }
 },[companyDataFetched ])

不要在onClick 而是通過說setCompanyDataFetch(true)來觸發按鈕中的提取。

然后將useEffectcompanyDataFetch作為依賴項。

function fetchData() {  
   return axios.get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`)
         .then((res) => {
           // setResponse(res.data);
           // setCompanyDataFetched(true);
           return res;
         })
         .catch((error) => {
           console.log(error);
         });
}

你的useEffect看起來像這樣

  useEffect(() => {
    let isMounted = true;
    if (companyDataFetched) {
      (async () => {
       const response = await fetchData() 
       if (isMounted) setState((prevState) => {
                        return {
                          ...prevState,
                          nume: response.name,
                          adresa: response.address,
                          telefon: response.phone,
                          fax: response.fax
                        }
                      });   
      if (isMounted) setCompanyDataFetched(false);      
     })();
    }
    return function () {
      isMounted = false;
    };
  }, [companyDataFetched]); 

經過大量研究,我發現我以錯誤的方式設置輸入字段值。 顯然,在使用 antd Form 時,必須對其進行初始化,並使用它的引用來動態改變 Form.Item 的值,如下所示:

const [form] = Form.useForm();
const [step, setStep] = useState(1);
const [state, setState] = useState({
  name: "",
  cif: "",
  address: "",
  phone: "",
  fax: "",
  contactName: "",
  email: "",
  password: "",
});

const fetchCompanyData = async () => {
  const response = await axios.get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`);

    setState((prevState) => {
      return {
        ...prevState,
        nume: response.data.denumire,
        adresa: response.data.adresa,
        telefon: response.data.telefon,
        fax: response.data.fax,
      };
    });

    form.setFieldsValue({
      nume: response.data.denumire,
      cif: state.cif,
      adresa: response.data.adresa,
      telefon: response.data.telefon,
      fax: response.data.fax,
    });

    setStep(2);
  };
};

[...]

{step === 1 && (
<CustomForm form={form} layout={theme.layout} widthelem={"70%"}>
  <Form.Item
    name="Company name:"
    label="Company name:"
    rules={[
      {
        pattern: new RegExp(/^\d{2,10}$/),
        message: "Invalid CIF!",
      },
      {
        required: true,
        message: "Please insert the company CIF!",
      },
    ]}
  >
    <CustomInput
      backgroundcolor={theme.white}
      onChange={(event) => handleChange(event, "cif")}
    />
  </Form.Item>
  <CustomButton
    backgroundcolor={theme.primaryColor}
    textcolor={theme.white}
    onClick={fetchCompanyData}
    margintop={"13%"}
    marginbottom={"13%"}
  >
    Continue
  </CustomButton>
<CustomForm>
)}
{step === 2 && (
<CustomForm form={form} layout={theme.layout} widthelem={"70%"}>
  <Form.Item
    name="Company name:"
    label="Company name:"
    rules={[
      {
        required: true,
        message: "Please insert the name of the company!",
        whitespace: true,
      },
    ]}
  >
    <CustomInput
      backgroundcolor={theme.white}
      onChange={(event) => handleChange(event, "name")}
    />
  </Form.Item>
  [...]
<CustomForm>
)}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM