获取后的表单验证 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>
我从 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>