Home > Blockchain >  Form Validation after fetch api / react
Form Validation after fetch api / react

Time:03-26

I fetching data from API to the fields input and by default, the values come from API. After fetching I have the edit button and after click, I can edit the values in form fields. So, please, can someone tell me how to add validation on inputs (for example if empty inputs, after click save show the message in inputs "empty value" and red border on this input) Thank you

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;

CodePudding user response:

You may check 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>
  • Related