【发布时间】:2021-04-09 13:31:19
【问题描述】:
我有这个 UserEditScreen.js 文件,我通过 React-Redux 从 mongodb 提取所有数据。
我需要进行一些验证,所以我使用了React Hook Form 来执行此操作。所以在我的代码上:
import React, { useState, useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { useDispatch, useSelector } from 'react-redux'
import Message from '../components/Message'
import Loader from '../components/Loader'
import { getUserDetails, updateUser } from '../actions/userActions'
import { USER_UPDATE_RESET } from '../constants/userConstants'
const UserEditScreen = ({ match, history }) => {
const { watch, register, errors, handleSubmit } = useForm()
console.log('role')
const userId = match.params.id
// const [name, setName] = useState('')
// const [email, setEmail] = useState('')
// const [phone, setPhone] = useState('')
// const [role, setRole] = useState('')
const dispatch = useDispatch()
const userDetails = useSelector(state => state.userDetails)
const { loading, error, user } = userDetails
const userUpdate = useSelector(state => state.userUpdate)
const { loading:loadingUpdate, error:errorUpdate, success:successUpdate } = userUpdate
useEffect(() => {
if(successUpdate){
dispatch({ type: USER_UPDATE_RESET })
history.push('/admin/userslist')
} else {
if(!user.name || user._id !== userId){
dispatch(getUserDetails(userId))
}
// else {
// setName(user.name)
// setEmail(user.email)
// setPhone(user.phone)
// setRole(user.role)
// }
}
}, [dispatch, history, userId, user, successUpdate])
const submitHandler = (data, e) => {
e.preventDefault()
const {name, email, phone, role } = data
dispatch(updateUser({ _id: userId, name, email, phone, role }))
}
return (
<>
<h1>Edit User</h1>
{ loadingUpdate && <Loader /> }
{ errorUpdate && <Message variant='danger'>{errorUpdate}</Message>}
{ loading ? <Loader /> : error ? <Message variant='danger'>{error}</Message> : (
<form onSubmit={submitHandler}>
<div className="form-group">
<label for="name">Name</label>
<input
type="text"
name="name"
value={user.name}
className={`form-control ${errors.name ? 'is-invalid' : ''}`}
id="name"
ref={register({ required: true, minLength: 2, maxLength: 30 })}
/>
{ errors.name && errors.name.type ==='required' && <p className="text-danger">Name is required.</p> }
{ errors.name && errors.name.type ==='minLength' && <p className="text-danger">Name is too short.</p> }
{ errors.name && errors.name.type ==='maxLength' && <p className="text-danger">Name is exceeds maximum length.</p> }
</div>
<div className="form-group">
<label for="email">Email address</label>
<input
type="email"
name="email"
value={user.email}
className={`form-control ${errors.email ? 'is-invalid' : ''}`}
id="email"
ref={register({ required: true, minLength: 8, maxLength: 30, pattern: /^\S+@\S+\.\S+$/ })}
/>
{ errors.email && errors.email.type ==='required' && <p className="text-danger">Email is required.</p> }
{ errors.email && errors.email.type ==='minLength' && <p className="text-danger">Email length is too small.</p> }
{ errors.email && errors.email.type ==='maxLength' && <p className="text-danger">Email exceeds maximum length.</p> }
{ errors.email && errors.email.type ==='pattern' && <p className="text-danger">That is not a valid email.</p> }
</div>
<div className="form-group">
<label for="phone">Phone</label>
<input
type="text"
value={user.phone}
className={`form-control ${errors.phone ? 'is-invalid' : ''}`}
id="phone"
ref={register({ required: true, minLength: 10, maxLength: 13, pattern: /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/})}
/>
{ errors.phone && errors.phone.type ==='required' && <p className="text-danger">Phone is required.</p> }
{ errors.phone && errors.phone.type ==='minLength' && <p className="text-danger">Phone length is too small.</p> }
{ errors.phone && errors.phone.type ==='maxLength' && <p className="text-danger">Phone exceeds maximum length.</p> }
{ errors.phone && errors.phone.type ==='pattern' && <p className="text-danger">Phone is not a valid phone.</p> }
</div>
<div className="form-group">
<label for="phone">User Role</label>
<div class="role">
<input
type="radio"
className="btn-check"
name="role"
id="administrator"
autocomplete="off"
value='administrator'
ref={register({ required: true })}
checked={user.role === 'administrator'}
/>
<label className="btn btn-outline-success" for="administrator">Administrator</label>
<input
type="radio"
className="btn-check"
name="role"
id="resort-owner"
autocomplete="off"
value='resortOwner'
ref={register({ required: true })}
checked={user.role === 'resortOwner'}
/>
<label className="btn btn-outline-success" for="resort-owner">Resort Owner</label>
<input
type="radio"
className="btn-check"
name="role"
id="reviewer"
autocomplete="off"
value='reviewer'
ref={register({ required: true })}
checked={user.role === 'reviewer'}
/>
<label className="btn btn-outline-success" for="reviewer">Reviewer</label>
{ errors.role && errors.role.type ==='required' && <p className="text-danger">Choose a role.</p> }
</div>
</div>
<button type="submit" className="btn btn-primary">Update</button>
</form>
)}
</>
)
}
export default UserEditScreen
如您所见,我注释掉了useState 字段并尝试通过user.name、user.email 等直接从userDetails 操作中提取数据。我通过每个输入字段值属性设置了这些数据。
但是,执行此操作后,我无法再修改或编辑任何字段。我需要设置一些验证,但希望仍然能够编辑每个字段并使用 react hook 表单提交表单,但我不知道如何解决这个问题。
知道如何解决这个问题并使表单字段可编辑以及能够使用反应钩子表单提交带有验证的表单吗?请帮忙。
更新:我尝试使用defaultValue 而不是value,因此它适用于姓名、电子邮件、电话,但现在我无法选择或修改单选按钮role 的值一。这是我更新的代码。
const UserEditScreen = ({ match, history }) => {
const { watch, register, errors, handleSubmit } = useForm()
console.log(watch('name'))
console.log(watch('email'))
console.log(watch('phone'))
console.log(watch('role'))
const userId = match.params.id
// const [name, setName] = useState('')
// const [email, setEmail] = useState('')
// const [phone, setPhone] = useState('')
// const [role, setRole] = useState('')
const dispatch = useDispatch()
const userDetails = useSelector(state => state.userDetails)
const { loading, error, user } = userDetails
const userUpdate = useSelector(state => state.userUpdate)
const { loading:loadingUpdate, error:errorUpdate, success:successUpdate } = userUpdate
useEffect(() => {
if(successUpdate){
dispatch({ type: USER_UPDATE_RESET })
history.push('/admin/userslist')
} else {
if(!user.name || user._id !== userId){
dispatch(getUserDetails(userId))
}
// else {
// setName(user.name)
// setEmail(user.email)
// setPhone(user.phone)
// setRole(user.role)
// }
}
}, [dispatch, history, userId, user, successUpdate,])
const submitHandler = (data, e) => {
e.preventDefault()
const {name, email, phone, role } = data
dispatch(updateUser({ _id: userId, name, email, phone, role }))
}
return (
<>
<h1>Edit User</h1>
{ loadingUpdate && <Loader /> }
{ errorUpdate && <Message variant='danger'>{errorUpdate}</Message>}
{ loading ? <Loader /> : error ? <Message variant='danger'>{error}</Message> : (
<form onSubmit={handleSubmit(submitHandler)}>
<div className="form-group">
<label for="name">Name</label>
<input
type="text"
name="name"
defaultValue={user.name}
className={`form-control ${errors.name ? 'is-invalid' : ''}`}
id="name"
ref={register({ required: true, minLength: 2, maxLength: 30 })}
/>
{ errors.name && errors.name.type ==='required' && <p className="text-danger">Name is required.</p> }
{ errors.name && errors.name.type ==='minLength' && <p className="text-danger">Name is too short.</p> }
{ errors.name && errors.name.type ==='maxLength' && <p className="text-danger">Name is exceeds maximum length.</p> }
</div>
<div className="form-group">
<label for="email">Email address</label>
<input
type="email"
name="email"
defaultValue={user.email}
className={`form-control ${errors.email ? 'is-invalid' : ''}`}
id="email"
ref={register({ required: true, minLength: 8, maxLength: 30, pattern: /^\S+@\S+\.\S+$/ })}
/>
{ errors.email && errors.email.type ==='required' && <p className="text-danger">Email is required.</p> }
{ errors.email && errors.email.type ==='minLength' && <p className="text-danger">Email length is too small.</p> }
{ errors.email && errors.email.type ==='maxLength' && <p className="text-danger">Email exceeds maximum length.</p> }
{ errors.email && errors.email.type ==='pattern' && <p className="text-danger">That is not a valid email.</p> }
</div>
<div className="form-group">
<label for="phone">Phone</label>
<input
type="text"
name="phone"
defaultValue={user.phone}
className={`form-control ${errors.phone ? 'is-invalid' : ''}`}
id="phone"
ref={register({ required: true, minLength: 10, maxLength: 13 })}
/>
{ errors.phone && errors.phone.type ==='required' && <p className="text-danger">Phone is required.</p> }
{ errors.phone && errors.phone.type ==='minLength' && <p className="text-danger">Phone length is too small.</p> }
{ errors.phone && errors.phone.type ==='maxLength' && <p className="text-danger">Phone exceeds maximum length.</p> }
{ errors.phone && errors.phone.type ==='pattern' && <p className="text-danger">Phone is not a valid phone.</p> }
</div>
<div className="form-group">
<label for="phone">User Role</label>
<div class="role">
<input
type="radio"
className="btn-check"
name="role"
id="administrator"
autocomplete="off"
value='administrator'
ref={register({ required: true })}
checked={user.role === 'administrator'}
/>
<label className="btn btn-outline-success" for="administrator">Administrator</label>
<input
type="radio"
className="btn-check"
name="role"
id="resort-owner"
autocomplete="off"
value='resortOwner'
ref={register({ required: true })}
checked={user.role === 'resortOwner'}
/>
<label className="btn btn-outline-success" for="resort-owner">Resort Owner</label>
<input
type="radio"
className="btn-check"
name="role"
id="reviewer"
autocomplete="off"
value='reviewer'
ref={register({ required: true })}
checked={user.role === 'reviewer'}
/>
<label className="btn btn-outline-success" for="reviewer">Reviewer</label>
{ errors.role && errors.role.type ==='required' && <p className="text-danger">Choose a role.</p> }
</div>
</div>
<button type="submit" className="btn btn-primary">Update</button>
</form>
)}
</>
)
}
【问题讨论】:
-
你试过用
defaultValue代替value吗? -
我做了,但它不会观看或编辑
phone或role(单选按钮)有什么想法吗? -
我尝试在
phone和role上使用watch来控制台记录它们,但我无法更改或修改它们。 -
更新:我尝试使用 defaultValue 而不是 value,因此它适用于姓名、电子邮件、电话,但现在我无法选择或修改单选按钮一的角色值。更新了上面的代码。
标签: node.js reactjs mongodb express react-redux