Я построил пользовательский крючок для обработки формы. У меня проблемы с вызовом проверки при изменении входного значения.
У меня есть четыре фрагмента кода. Второе и третье только для контекста, чтобы показать, как завершен пользовательский хук, но не стесняйтесь их пропускать, поскольку мне просто интересно, как реализовать подобную функциональность из фрагмента 1 в фрагменте 4.
Причина, по которой я хочу чтобы сделать это, в дополнение к вызову его при отправке, в том случае, если входное значение становится '', я хотел бы отобразить сообщение об ошибке, и когда пользователь начнет печатать, оно будет go прочь.
Это было довольно просто, когда я не использовал ловушки, я бы просто вызывал функцию проверки после setState, как это:
const validate = (name) => {
switch(name):
case "username":
if(!values.username) {
errors.username = "What's your username?";
}
break;
default:
if(!values.username) {
errors.username = "What's your username?";
}
if(!values.password) {
errors.username = "What's your password?";
}
break;
}
const handleChange = (e) => {
let { name, value } = e.target;
this.setState({ ...values,
[name]: value
}, () => this.validate(name))
}
Так что теперь с использованием реагирующих ловушек все не так просто. Я создал собственный обработчик форм, который возвращает значения, ошибки, handleChange и handleSubmit. Обработчику формы передается initialState, функция проверки и обратный вызов. На данный момент это выглядит так:
import useForm from './form.handler.js';
import validate from './form.validation.js';
const schema = { username: "", password: "" }
export default function Form() {
const { values, errors, handleChange, handleSubmit } = useForm(schema, validate, submit);
function submit() {
console.log('submit:', values);
}
return (
<form></form> // form stuff
)
}
Вот файл проверки. Это просто, просто нужны значения для двух полей.
export default function validate(values) {
let errors = {};
if(!values.username) {
errors.username = "What's your username?";
}
if(!values.password) {
errors.password = "What's your password?";
}
return errors;
}
Теперь вот мой обработчик форм, где я пытаюсь решить эту проблему. Я пробовал разные вещи вокруг вызова setErrors (validate (values)) в useEffect, но не могу получить доступ к входным данным. Я не уверен, но в настоящее время пользовательский хук выглядит так:
import { useState, useEffect, useCallback } from 'react';
export default function useForm(schema, validate, callback) {
const [values, setValues] = useState(schema),
[errors, setErrors] = useState({}),
[loading, setLoading] = useState(false); // true when form is submitting
useEffect(() => {
if(Object.keys(errors).length === 0 && loading) {
callback();
}
setLoading(false);
}, [errors, loading, callback])
// I see useCallback used for event handler's. Not part of my questions, but is it to prevent possible memory leak?
const handleChange = (e) => {
let { name, value } = e.target;
setValues({ ...values, [name]: value });
}
const handleSubmit = (e) => {
e.preventDefault();
setLoading(true);
setErrors(validate(values));
}
return { values, errors, handleChange, handleSubmit }
}