获取后的表单验证 api / 反应

Form Validation after fetch api / react

我从 API 获取数据到字段输入,默认情况下,值来自 API。获取后我有编辑按钮,点击后,我可以编辑表单字段中的值。所以,有人能告诉我如何在输入上添加验证吗(例如,如果输入为空,单击保存后在输入中显示消息“空值”和此输入上的红色边框) 谢谢

import React, { useEffect, useState, useRef } from "react";
import { useParams, Link } from "react-router-dom";
import { useGlobalContext } from "../context";
import styled from "styled-components";
import Sort from "../components/sort";

const urlID = "https://jsonplaceholder.typicode.com/users?id=";

const Profile = () => {
  const { id } = useParams();
  const [user, setUser] = useState([]);
  const [isReadOnly, setIsReadOnly] = useState(true);
  const [isEdit, setIsEdit] = useState(false);
  const form = useRef(null);

  const fetchUser = async (urlID) => {
    try {
      const response = await fetch(urlID);
      const data = await response.json();
      if (data) {
        const { name, username, email, phone, website } = data[0];
        const { street, city, zipcode } = data[0].address;

        const newPerson = {
          name,
          username,
          email,
          phone,
          website,
          street,
          city,
          zipcode,
        };
        setUser(newPerson);
      } else {
        setUser(null);
      }
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    fetchUser(`${urlID}${id}`);
  }, [id]);

  const editInput = () => {
    setIsEdit(true);
    setIsReadOnly(false);
  };

  const handleSubmit = (e) => {
    e.preventDefault();

    const data = new FormData(form.current);

    const value = Object.fromEntries(data.entries());
    // value.user = data.getAll("name");
    console.log(value);
    setIsEdit(false);
    setIsReadOnly(true);
  };
  const handleChange = (e) => {
    setUser({
      ...user,
      [e.target.name]: e.target.value,
    });
  };

  return (
    <main>
      <Wrapper>
        <Sort />
        <div>
          <header>
            <h3>User profile</h3>
            <button onClick={() => editInput()} className='btn'>
              Edit
            </button>
          </header>

          <form className='form' ref={form} onSubmit={handleSubmit}>
            <div className='form-control'>
              <label htmlFor='name'>Name</label>
              <input
                name='name'
                type='name'
                defaultValue={user.name}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>

            <div className='form-control'>
              <label htmlFor='username'>Username</label>
              <input
                name='username'
                type='username'
                defaultValue={user.username}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>
            <div className='form-control'>
              <label htmlFor='email'>Email</label>
              <input
                name='email'
                type='email'
                defaultValue={user.email}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>
            <div className='form-control'>
              <label htmlFor='street'>Street</label>
              <input
                type='street'
                name='street'
                defaultValue={user.street}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>
            <div className='form-control'>
              <label htmlFor='city'>City</label>
              <input
                type='city'
                name='city'
                defaultValue={user.city}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>
            <div className='form-control'>
              <label htmlFor='zipcode'>Zip code</label>
              <input
                type='zipcode'
                name='zipcode'
                defaultValue={user.zipcode}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>
            <div className='form-control'>
              <label htmlFor='website'>Website</label>
              <input
                type='website'
                name='website'
                defaultValue={user.website}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>
            <div className='form-control'>
              <label htmlFor='phone'>Phone</label>
              <input
                type='phone'
                name='phone'
                defaultValue={user.phone}
                readOnly={isReadOnly}
                style={
                  !isEdit
                    ? { color: "rgba(0, 0, 0, 0.3)" }
                    : { color: "#000000" }
                }
                onChange={handleChange}
              />
            </div>
            <div className='form-control'>
              <label htmlFor='comment'>Comment</label>
              <textarea
                name='textarea'
                id=''
                cols='30'
                rows='10'
                readOnly={isReadOnly}
                onChange={handleChange}
              ></textarea>
            </div>
            <div className='btn-container'>
              <Link to='/' className='btn'>
                Back
              </Link>
              <button
                type='submit'
                className='btn-submit'
                disabled={isReadOnly}
                style={
                  !isEdit
                    ? { backgroundColor: "#afafaf" }
                    : { backgroundColor: "#52CF4F" }
                }
                onClick={handleSubmit}
              >
                Save
              </button>
            </div>
          </form>
        </div>
      </Wrapper>
    </main>
  );
};

const Wrapper = styled.section`
  display: grid;
  grid-template-columns: 1fr 2fr;
  max-width: 665px;
  width: 90vw;
  gap: 2rem;
  h3 {
    font-style: normal;
    font-weight: 700;
    font-size: 14px;
    line-height: 16px;
    color: #000000;
  }
  .btn {
    background: #4b51ef;
    border-radius: 5px;
    padding: 6px 11px;
    font-weight: 400;
    font-size: 12px;
    line-height: 14px;
    color: #ffffff;
    border: transparent;
    text-decoration: none;
  }
  header {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .form {
    display: grid;
    gap: 10px;

    padding: 20px 0 20px 12px;
    background: #ffffff;
    border: 2px solid #f3f3f3;
    border-radius: 8px;
    box-sizing: border-box;
  }
  .form-control {
    display: flex;
    flex-direction: column;
    gap: 3px;
    max-width: 210px;
  }
  .form-control label {
    font-weight: 400;
    font-size: 8px;
    line-height: 9px;
    color: #000000;
  }
  .form-control input,
  textarea {
    font-weight: 400;
    font-size: 10px;
    line-height: 12px;
    /* color: rgba(0, 0, 0, 0.3); */
    padding: 5px 0 5px 10px;
    background: #ffffff;
    border: 1px solid #d8d8d8;
    border-radius: 5px;
  }
  /* input:invalid {
    border-color: red;
  } */
  .btn-container {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .btn-submit {
    background: #afafaf;
    border-radius: 5px;
    border: transparent;
    padding: 5px 15px;
    font-weight: 400;
    font-size: 12px;
    line-height: 14px;
    color: #ffffff;
    margin-left: 10px;
  }
`;

export default Profile;

您可以查看Formik

<Formik
   initialValues={{
     firstName: '',
     lastName: '',
     email: '',
   }}
   validationSchema={SignupSchema}
   onSubmit={values => {
     // same shape as initial values
     console.log(values);
   }}
 >
   {({ errors, touched }) => (
     <Form>
       <Field name="firstName" />
       {errors.firstName && touched.firstName ? (
         <div>{errors.firstName}</div>
       ) : null}
       <Field name="lastName" />
       {errors.lastName && touched.lastName ? (
         <div>{errors.lastName}</div>
       ) : null}
       <Field name="email" type="email" />
       {errors.email && touched.email ? <div>{errors.email}</div> : null}
       <button type="submit">Submit</button>
     </Form>
   )}
 </Formik>