我正在嘗試構建一個功能,當用戶離開表單時,即當組件卸載時,它應該觸發保存,即將表單資料發布到服務器。僅當表單資料發生任何更改時才會發生這種情況。任何人都可以指導我為什么會發生這種情況。我嘗試過基于類的方法,但我不想重構我的生產代碼。
import { useCallback, useEffect, useState } from "react";
import React from "react";
import * as _ from "lodash";
import { useFormik } from "formik";
// for now this is hardcoded here..but let's assume
// this server data will be loaded when component mounts
const serverData = {
choice: "yes",
comment: "some existing comment"
};
const availableChoices = ["yes", "no"];
const Form = () => {
const formik = useFormik({ initialValues: { ...serverData } });
const [isFormChanged, setIsFormChanged] = useState(false);
const valuesHaveChanged = React.memo(() => {
console.log("INIT VALUES= ", formik.initialValues);
console.log("FINAL VALUES = ", formik.values);
return !_.isEqual(formik.initialValues, formik.values);
}, [formik.initialValues, formik.values]);
const triggerSave = () => console.log("Save");
useEffect(() => {
// setForm({ ...serverData });
if (valuesHaveChanged) {
setIsFormChanged(true);
}
return () => {
// when this cleanup function runs
// i.e when this component unmounts,
// i need to check if there
// was any change in the form state
// if there was a change i need to trigger a save
// i.e post form data to server.
if (setIsFormChanged) {
triggerSave();
}
};
});
return (
<form>
<div className="form-group">
{availableChoices.map((choice) => (
<label key={choice}>
{choice}
<input
id="choice"
value={choice}
className="form-control"
type="radio"
name="choice"
checked={choice === formik.values.choice}
onChange={formik.handleChange}
/>
</label>
))}
</div>
<div className="form-group">
<textarea
rows="5"
cols="30"
id="comment"
name="comment"
value={formik.values.comment}
onChange={formik.handleChange}
className="form-control"
placeholder="some text..."
></textarea>
</div>
</form>
);
};
export default Form;
uj5u.com熱心網友回復:
我發現的第一個問題是依賴陣列。
useEffect(() => {
// the flag can be set anytime upon a field has changed
// maybe formik has a value like that, read doc
if (valuesHaveChanged) {
setIsFormChanged(true);
}
return () => {
if (setIsFormChanged) {
triggerSave();
}
}
// the dependency array is [], can't be missed
}, [])
當前,您正在呼叫此效果并在每次更新中清除此效果,例如。如果此組件中的任何值發生變化。但通常你只想在下馬時做一次。
即使你做對了上面的事情,你仍然需要確保你的代碼不包含記憶體泄漏,因為你試圖在下馬時做一些事情。所以最好傳遞值:
triggerSave([...formik.values])
并確保在里面triggerSave,您不會意外地呼叫任何關于formik或 的內容setState。
uj5u.com熱心網友回復:
嘗試使用useEffect依賴項
useEffect(() => {
return () => {
// when this cleanup function runs
// i.e when this component unmounts,
// i need to check if there
// was any change in the form state
// if there was a change i need to trigger a save
// i.e post form data to server.
if (!_.isEqual(formik.initialValues, formik.values)) {
triggerSave();
}
};
}, [formik.values]); // won't run on every render but just on formik.values update
解釋:
useEffect將依賴項作為第二個引數,如果[]傳遞 - 效果僅在安裝時觸發,如果[...]通過,將在第一次安裝和任何...更新時觸發。
如果您不通過第二個 agrument,則useEffect作為每次渲染的效果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/364979.html
