Я использую React Hook Form v7 и пытаюсь сделать свою форму данных постоянной при перезагрузке страницы. Я прочитал официальный документация РХФ, в котором предлагается использовать маленькая государственная машина, и попытался реализовать его, но безуспешно. Есть ли лучший способ сделать это? Однако...
Первая проблема, с которой я столкнулся при его использовании, заключается в том, что мои данные представляют собой сложный объект, поэтому updateAction это должно быть не так просто.
Вторая проблема заключается в том, что я не знаю, когда и как запустить updateAction для сохранения данных. Должен ли я запускать его при размытии ввода? При изменении входа?
Вот мой тестовый код:
@HugoBp Что вы подразумеваете под «всем приложением»? Я имею в виду, что если пользователь нажимает кнопку обновления браузера, данные сохраняются.
Хорошо, я действительно спрашивал, говорите ли вы о сохранении данных при изменении страницы в вашем приложении, потому что об этом говорится в документации RHF, на которую вы ссылаетесь. Теперь я понимаю, что это не то, что вам нужно.





Само состояние не будет сохранять никаких данных при перезагрузке страницы.
Вам нужно добавить данные о состоянии в локальное хранилище.
Затем загрузите его обратно в состояние на componentDidMount (useEffect с пустым массивом зависимостей).
const Form = () => {
const [formData, setFormData] = useState({})
useEffect(() => {
if (localStorage) {
const formDataFromLocalStorage = localStorage.getItem('formData');
if (formDataFromLocalStorage) {
const formDataCopy = JSON.parse(formDataFromLocalStorage)
setFormData({...formDataCopy})
}
}
}, []);
useEffect(() => {
localStorage && localStorage.setItem("formData", JSON.stringify(formData))
}, [formData]);
const handleInputsChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value
})
}
return (
<div>
<input
type = "text"
name = "firstName"
placeholder='first name'
onChange = {e => handleInputsChange(e)}
value = {formData?.firstName}
/>
<input
type = "text"
name = "lastName"
placeholder='last name'
onChange = {e => handleInputsChange(e)}
value = {formData?.lastName}
/>
</div>
)
}
Спасибо за ваш ответ, но он не работает для моего примера (пожалуйста, проверьте мой CodeSandbox). Я использую RHF, и мои данные формы представляют собой сложный объект.
Я имею в виду, что использование useEffect для установки localStorage, я думаю, может быть хорошей идеей использовать little-state-machine, но как я могу обновить весь объект состояния RHF? Я мог бы наблюдать за каждым изменением, используя methods.watch(), но тогда я должен обновить состояние RHF новым. Как?
Если вам помогает сохранение в localStorage, вот как я этого добился.
Определите пользовательский хук для сохранения данных
export const usePersistForm = ({
value,
localStorageKey,
}) => {
useEffect(() => {
localStorage.setItem(localStorageKey, JSON.stringify(value));
}, [value, localStorageKey]);
return;
};
Просто используйте его в компоненте формы
const FORM_DATA_KEY = "app_form_local_data";
export const AppForm = ({
initialValues,
handleFormSubmit,
}) => {
// useCallback may not be needed, you can use a function
// This was to improve performance since i was using modals
const getSavedData = useCallback(() => {
let data = localStorage.getItem(FORM_DATA_KEY);
if (data) {
// Parse it to a javaScript object
try {
data = JSON.parse(data);
} catch (err) {
console.info(err);
}
return data;
}
return initialValues;
}, [initialValues]);
const {
handleSubmit,
register,
getValues,
formState: { errors },
} = useForm({ defaultValues: getSavedData() });
const onSubmit: SubmitHandler = (data) => {
// Clear from localStorage on submit
// if this doesn’t work for you, you can use setTimeout
// Better still you can clear on successful submission
localStorage.removeItem(FORM_DATA_KEY);
handleFormSubmit(data);
};
// getValues periodically retrieves the form data
usePersistForm({ value: getValues(), localStorageKey: FORM_DATA_KEY });
return (
<form onSubmit = {handleSubmit(onSubmit)}>
...
</form>
)
}
Не могли бы вы отредактировать мой пример CodeSandbox и показать мне, как это сделать в этом конкретном случае? Я пытался, но, похоже, не работает с моим примером формы. Я получаю много Uncaught TypeError: Cannot destructure property 'zip' of 'watch(...)' as it is undefined.. Как я уже писал, я имею дело со сложным объектом состояния.
Я редактировал CodeSandbox, попробуйте здесь codeandbox.io/embed/…
Я отредактировал сообщение, чтобы исправить ошибку, вам нужно проанализировать строки объекта для объекта javaScript, иначе он выдаст ошибку.
Спасибо, кажется, работает как шарм
Под перезагрузкой страницы вы имеете в виду, обновляет ли пользователь все приложение?