Как использовать Axios для отправки данных формы только тогда, когда форма правильно заполнена

Исходная информация:

Итак, я работаю над проектом, который включает отправку данных формы в базу данных. Пока я просто использую Mock API, чтобы все настроить и запустить перед настройкой базы данных в .NET.

Информация о пользовательском хуке и валидаторе:

Я использую пользовательский хук с двумя основными функциями: handleChangeEvent(), который отвечает за установку новых значений в основном компоненте, CreateUser, и handleSubmit(), который вызывает мой пользовательский валидатор (validateNewUser) для проверки ошибок в форма.

Мой хук и валидатор работают нормально, но у меня проблемы с почтовым запросом Axios. Я могу поместить свой почтовый запрос Axios в свой пользовательский хук, и он работает по назначению, но я не могу понять, как отправить форму в Mock API, только когда форма правильно заполнена.

Пробы и ошибки на данный момент:

Я попытался использовать оператор if в моей функции handlePost (что, как мне кажется, является правильным способом сделать это, я мог просто что-то упустить, я мог ошибаться), я попытался поместить запрос Axios внутри функции handlePost, но это дало Нет прогресса.

То, как я его установил, в настоящее время работает, но в основном каждый раз, когда вы нажимаете «Отправить», он отправляет данные в API, скорее всего, потому, что он каждый раз отправляет форму. Другой способ, которым я мог бы это сделать, - это настроить всплывающие сообщения об ошибках, когда пользователь заполняет форму? Чтобы форма была точной еще до ее отправки.

Я новичок в React, поэтому прошу прощения, если мой вопрос/проблема сбивает с толку. Если нужна дополнительная информация, я предоставлю все, что смогу.

Код для всех задействованных частей будет ниже, и мы будем очень признательны за любой ввод.

Основной код:

использоватьCreateUser.jsx:

import { useState } from 'react';
import axios from 'axios';

const useCreateUser = (validateNewUser) => {
    const [values, setValues] = useState({
        firstName: '',
        lastName: '',
        email: '',
        password: ''
    });

    const [errors, setErrors] = useState({});

    const handleChangeEvent = e => {
        const {name, value} = e.target
        setValues({
            ...values,
            [name]: value
        });
    };

    const handleSubmit = e => {
    e.preventDefault();
    setErrors(validateNewUser(values));

    const user = {
        firstName: values.firstName,
        lastName: values.lastName,
        email: values.email,
        password: values.password
        };

    if (handleSubmit){
        axios.post(url, user)
        .then((response) => {
        console.info(response.data);
    })
    }
}

  return {handleChangeEvent, values, handleSubmit, errors}
}

export default useCreateUser;

валидатеневусер.jsx:

export default function validateNewUser(values) {
    let errors = {}

    //Validate First Name
    if (!values.firstName.trim()) {
        errors.firstName = 'First Name is Required.'
    }

    //Validate Last Name
    if (!values.lastName.trim()) {
        errors.lastName = 'Last Name is Required.'
    }

    //Validate Email
    if (!values.email){
        errors.email = 'Email is Required.'
    } else if (!/\S+@\S+\.\S+/.test(values.email)) {
        errors.email = 'Invalid Email Address.'
    }

    if (!values.password){
        errors.password = 'Password is Required.'
    } else if (values.password.length < 6) {
        errors.password = 'Password must be greater than 6 characters.'
    }

    return errors;

}

CreateUser.jsx:

import Header from "../Header";
import { Form, Button } from "semantic-ui-react";
import { Box } from "@mui/material";
import useCreateUser from "../../hooks/useCreateUser";
import validateNewUser from "../../validators/validateNewUser";

const CreateUser = () => {
    const {handleChangeEvent, values, handleSubmit, errors} = useCreateUser(validateNewUser);
    
    return (
    <Box m = "20px">
        <Box 
        display = "flex" 
        justifyContent = "space-between" 
        alignItems = "center"
        margin = "0 auto"
        marginBottom = "20px"
        >
            <Header title = "Create a New User" subtitle = "Please ensure to select the correct role."/>
        </Box>

        <Form onSubmit = {handleSubmit}>
            <Form.Field>
                <label>First Name</label>
                <input placeholder='First Name' name='firstName' type='text' value = {values.firstName} onChange = {handleChangeEvent} />
                {errors.firstName && <p style = {{color: "red"}}>{errors.firstName}</p>}
            </Form.Field>
            <Form.Field>
                <label>Last Name</label>
                <input placeholder='Last Name' name='lastName' type='text' value = {values.lastName}  onChange = {handleChangeEvent} />
                {errors.lastName && <p style = {{color: "red"}}>{errors.lastName}</p>}
            </Form.Field>
            <Form.Field>
                <label>Email</label>
                <input placeholder='Email' name='email' type='email' value = {values.email} onChange = {handleChangeEvent} />
                {errors.email && <p style = {{color: "red"}}>{errors.email}</p>}
            </Form.Field>
            <Form.Field>
                <label>Password</label>
                <input placeholder='Password' name='password' type='password' value = {values.password} onChange = {handleChangeEvent} />
                {errors.password && <p style = {{color: "red"}}>{errors.password}</p>}
            </Form.Field>
            <Button type='submit'}>Submit</Button>
        </Form>
    </Box>
    )

}


export default CreateUser;

🤔 А знаете ли вы, что...
С React можно создавать одностраничные приложения (SPA), не перезагружая страницу.


60
1

Ответ:

Решено

Несколько указателей Лучше давать обратную связь пользователю по мере того, как он вводит данные

// validate on change
const handleChangeEvent = e => {

    const { name, value } = e.target;

    const updatedValues = { ...values, [name]: value };

    setValues(updatedValues)

    const validationErrors = validateNewUser(updatedValues);

    setErrors(validationErrors)

};

При отправке вы можете вернуть первую ошибку, чтобы форма могла прокручиваться или фокусироваться на поле с ошибкой.

const handleSubmit = async (e) => {

    e.preventDefault();
  
    // this might  not be needed
    // you can do validations which need api calls
    // but event those can be done on input
    // setErrors(validateNewUser(values));

    // return error code
    const firstErrorKey = Object.keys(error)[0]
    if (firstErrorKey !== undefined) {
       return { hasError: true } 
    }

    const user = {
        firstName: values.firstName,
        lastName: values.lastName,
        email: values.email,
        password: values.password
    };

    const response = await axios.post(url, user)
    console.info(response.data);

    // return success code depending on server response
    // so u can show success
    // return { isSuccess: response.data?.code === 0 } 

    }
}

в форме вы можете установить загрузчик установить загрузчик

 const onFormSubmit = async e => {
   try {

      setState('submitting')

      const response = await handleSubmit(e);

      if (response.isSuccess) {
        // show alert/toast
      }

     if (response.hasErrors) {
       // focus on first error control
        const firstErrorKey = Object.keys(error)[0]
        if (firstErrorKey !== undefined) {
           // focus on control with error
        }
     }

      setState('success')

   } catch(error) {
     setState('error')
   }
 }

 <Form onSubmit = {handleSubmit}>

 </Form>

Если вы можете отделить состояние ввода формы от логики API, это сделает код более удобным для сопровождения.

Если возможно, используйте такие библиотеки, как Formik, они обрабатывают состояние формы и позволяют вам сосредоточиться на бизнес-части кода, такой как вызов API, проверки.

Размышление о состояниях компонентов также поможет вам проектировать более качественные компоненты.

Надеюсь, это поможет в некотором роде,

Ваше здоровье