Лучшая практика для проверки ввода в то время как onChange внутри React пользовательский хук? - PullRequest
1 голос
/ 16 апреля 2020

Я построил пользовательский крючок для обработки формы. У меня проблемы с вызовом проверки при изменении входного значения.

У меня есть четыре фрагмента кода. Второе и третье только для контекста, чтобы показать, как завершен пользовательский хук, но не стесняйтесь их пропускать, поскольку мне просто интересно, как реализовать подобную функциональность из фрагмента 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 }
}

1 Ответ

1 голос
/ 16 апреля 2020

Я не уверен, стоит ли устанавливать другое состояние (ошибки) во время обратного вызова для установки состояния (значений), поэтому создал просмотр кода

Как прокомментировано; Вы можете установить ошибки при установке значений:

const Component = () => {
  const [values, setValues] = useState({});
  const [errors, setErrors] = useState({});
  const onChange = useCallback(
    (name, value) =>
      setValues((values) => {
        const newValues = { ...values, [name]: value };
        setErrors(validate(newValues));//set other state while in a callback
        return newValues;
      }),
    []
  );
  return <jsx />;
};

Или объединить значения и ошибки:

const Component = () => {
  const [form, setForm] = useState({
    values: {},
    errors: {},
  });
  const onChange = useCallback(
    (name, value) =>
      setForm((form) => {
        const values = { ...form.values, [name]: value };
        const errors = validate(values);
        return { values, errors };
      }),
    []
  );
  const { errors, values } = form;
  return <jsx />;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...