React:如果对象键值也是 true,则将 defaultChecked 设置为 true
2021-01-04
175
我有这个数据集,其中包含
amenities
,它也是对象中的对象:
{
name: "California Maki Resort",
price_per_night: 2804.0,
description:
"On a lush 16-hectare island with white-sand beaches, this relaxed resort is 5 km from the jetty in Cadiz Viejo, a village on the mainland.",
address: "Cadiz Viejo",
city: "Cadiz",
amenities:
{
tv: false,
reservation: false,
moderate_noise: true
},
image:
"https://images.unsplash.com/photo-1591017403286-fd8493524e1e"
}
如您所见,我在 amenities 下有
tv
、
reservation
和
moderate_noise
子字段。在我的编辑度假村屏幕上,我需要从 amenities 中提取数据,并在值为 true 时将其设置为
defaultChecked
。所以我所做的是像这样映射对象:
{
Object.keys(resort.amenities).reduce((result, key) => {
return (
<div className="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="tv"
defaultChecked={result["tv"] === true}
id="tv" value={true} ref={register} />
<label class="form-check-label" for="tv">TV</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="reservation"
defaultChecked={result["reservation"] === true}
id="reservation" value={true} ref={register}/>
<label class="form-check-label" for="reservation">Reservation</label>
</div>
)}
}
但这给了我一些错误,它无法读取
result["tv"]
我不确定是否正确检查了每个值是否为真,但我希望在复选框上选中它,如果数据库中的键(例如 tv)的值为真。请帮忙!
注意:
resort.amenities
返回上述对象数据并且工作正常,我只是无法运行,因为我认为我通过此对象进行映射的方式不正确。
更新:只是为了给你完整的代码图片,它是:
import axios from 'axios'
import React, { useState, useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { useDispatch, useSelector } from 'react-redux'
import { store } from 'react-notifications-component'
import 'react-notifications-component/dist/theme.css'
import 'animate.css'
import Message from '../components/Message'
import Loader from '../components/Loader'
import { listResortDetails, updateResort } from '../actions/resortActions'
import { RESORT_UPDATE_RESET } from '../constants/resortConstants'
const ResortEditAdminScreen = ({ match, history }) => {
const { register, errors, handleSubmit } = useForm()
const resortId = match.params.id
const [image, setImage] = useState('')
const [uploading, setUploading] = useState(false)
const dispatch = useDispatch()
const resortDetails = useSelector(state => state.resortDetails)
const { loading, error, resort } = resortDetails
const resortUpdate = useSelector(state => state.resortUpdate)
const {
loading: loadingUpdate,
error: errorUpdate,
success: successUpdate
} = resortUpdate
useEffect(() => {
console.log(resort.amenities)
if(successUpdate){
dispatch({ type: RESORT_UPDATE_RESET })
history.push('/admin/resortsList')
store.addNotification({
title: 'Success!',
message: 'Resort successfully updated.',
type: 'success',
container: 'top-right',
animationIn: ["animate__animated", "animate__fadeInRight"],
animationOut: ["animate__animated", "animate__fadeOutRight"],
dismiss: {
duration: 4000
}
})
} else {
if(!resort.name || resort._id !== resortId){
dispatch(listResortDetails(resortId))
}
}
}
}, [dispatch, history, resortId, resort, successUpdate])
const uploadFileHandler = async(e) => {
const file = e.target.files[0]
const formData = new FormData()
formData.append('image', file)
setUploading(true)
try{
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
const { data } = await axios.post('/api/upload', formData, config)
setImage(data)
setUploading(false)
} catch(error){
console.error(error)
setUploading(false)
}
}
const submitHandler = (data, e) => {
e.preventDefault()
const { name, pricePerNight, description, address, city, province, zipCode, phone, email, website, image, tv, reservation, moderateNoise, freeWifi, trendy, creditCard, bar, animals, kids } = data
dispatch(updateResort({
_id: resortId,
name,
price_per_night: pricePerNight,
description,
address,
city,
province,
zip_code: zipCode,
phone,
email,
website,
image,
amenities: {
tv,
reservation,
moderate_noise: moderateNoise,
free_wifi: freeWifi,
trendy,
credit_card: creditCard,
bar,
animals,
kids
}
}))
}
return (
<>
<h1>Edit Resort</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={resort.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="name">Price Per Night</label>
<input
type="text"
name="pricePerNight"
defaultValue={resort.price_per_night}
className={`form-control ${errors.pricePerNight ? 'is-invalid' : ''}`}
id="pricePerNight"
ref={register({ required: true, minLength: 2, maxLength: 5, pattern: /^-?(0|[1-9]\d*)?$/ })}
/>
{ errors.pricePerNight && errors.pricePerNight.type ==='required' && <p className="text-danger">Price is required.</p> }
{ errors.pricePerNight && errors.pricePerNight.type ==='minLength' && <p className="text-danger">Price is too small.</p> }
{ errors.pricePerNight && errors.pricePerNight.type ==='maxLength' && <p className="text-danger">Price exceeds maximum length.</p> }
{ errors.pricePerNight && errors.pricePerNight.type ==='pattern' && <p className="text-danger">That is not a valid price.</p> }
</div>
<div className="form-group">
<label for="description">Description</label>
<textarea
name="description"
defaultValue={resort.description}
className = {`form-control ${errors.description ? 'is-invalid' : ''}`}
id="description"
rows="5"
ref={register({ required: true, minLength: 100, maxLength: 500})}
/>
{errors.description && errors.description.type === 'required' && <p className="text-danger">Description is required.</p>}
{ errors.description && errors.description.type ==='minLength' && <p className="text-danger">Description is too short.</p> }
{ errors.description && errors.description.type === 'maxLength' && <p className="text-danger">Description exceeds maximum length.</p>}
</div>
<div className="form-group">
<label for="address">Address</label>
<input
type="text"
name="address"
defaultValue={resort.address}
className= {`form-control ${errors.address ? 'is-invalid' : ''}`}
id="address"
ref={register({ required: true })}
/>
{ errors.address && errors.address.type ==='required' && <p className="text-danger">Address is required.</p> }
</div>
<div className="form-group">
<label for="province">Province</label>
<input
type="text"
name="province"
defaultValue={resort.province}
className={`form-control ${errors.province ? 'is-invalid' : ''}`}
id="province"
ref={register({ required: true })}
/>
{ errors.province && errors.province.type ==='required' && <p className="text-danger">Province is required.</p> }
</div>
<div className="form-group">
<label for="zip_code">Zip Code</label>
<input
type="text"
name="zipCode"
defaultValue={resort.zip_code}
className={`form-control ${errors.zipCode ? 'is-invalid' : ''}`}
id="zipCode"
ref={register({ required: true, minLength: 4, maxLength: 4, pattern: /^[0-9]*$/ })}
/>
{ errors.zipCode && errors.zipCode.type === 'required' && <p className="text-danger">Zip Code is required.</p>}
{errors.zipCode && errors.zipCode.type === 'minLength' && <p className="text-danger">Zip Code must consist with 4 digits.</p>}
{ errors.zipCode && errors.zipCode.type === 'maxLength' && <p className="text-danger">Zip Code must consist with 4 digits.</p>}
{ errors.zipCode && errors.zipCode.type ==='pattern' && <p className="text-danger">Not a valid Zip Code.</p> }
</div>
<div className="form-group">
<label for="city">City</label>
<input
type="text"
name="city"
defaultValue={resort.city}
className={`form-control ${errors.city ? 'is-invalid' : ''}`}
id="city"
ref={register({ required: true })}
/>
{ errors.city && errors.city.type ==='required' && <p className="text-danger">City is required.</p> }
</div>
<div className="form-group">
<label for="phone">Phone</label>
<input
type="text"
name="phone"
defaultValue={resort.phone}
className={`form-control ${errors.phone ? 'is-invalid' : ''}`}
id="phone"
ref={register({ required: true, minLength: 10, maxLength: 13, pattern: /(^0|[89]\d{2}-\d{3}\-?\d{4}$)|(^0|[89]\d{2}\d{3}\d{4}$)|(^63[89]\d{2}-\d{3}-\d{4}$)|(^63[89]\d{2}\d{3}\d{4}$)|(^[+]63[89]\d{2}\d{3}\d{4}$)|(^[+]63[89]\d{2}-\d{3}-\d{4}$)|(^(\+\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="email">Email</label>
<input
type="email"
name="email"
defaultValue={resort.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="website">Website</label>
<input
type="text"
name="website"
defaultValue={resort.website}
className={`form-control ${errors.website ? 'is-invalid' : ''}`}
id="website"
ref={register({ required: true, pattern: /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/ })}
/>
{ errors.website && errors.website.type === 'required' && <p className="text-danger">Website is required.</p>}
{ errors.website && errors.website.type ==='pattern' && <p className="text-danger">Not a valid website url.</p> }
</div>
<div className="form-group">
<label for="uploadImage">Upload Image</label>
<input
type="file"
className="form-control-file"
id="uploadImage"
onChange={uploadFileHandler}
ref={register}
/>
</div>
{ uploading && <Loader /> }
{
Object.keys(resort.amenities).reduce((result, key) => {
return (
<div className="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="tv"
defaultChecked={result["tv"] === true}
id="tv" value={true} ref={register} />
<label class="form-check-label" for="tv">TV</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="reservation"
defaultChecked={resort.amenities.reservation === true}
id="reservation" value={true} ref={register}/>
<label class="form-check-label" for="reservation">Reservation</label>
</div>
</>
)}
export default ResortEditAdminScreen
更新:它显示此错误
TypeError:无法读取未定义的属性“tv”
3个回答
您不需要使用
Object.keys
和
reduce
,因为您可以直接从
amenities
对象获取值。
return (
<div className="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
name="tv"
defaultChecked={resort.amenities.tv === true}
id="tv"
value={true}
ref={register}
/>
<label class="form-check-label" for="tv">
TV
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
name="reservation"
defaultChecked={resort.amenities.reservation === true}
id="reservation"
value={true}
ref={register}
/>
<label class="form-check-label" for="reservation">
Reservation
</label>
</div>
</div>
)
Mark Skelton
2021-01-04
像这样使用 JS 地图:
return Object.keys(resort.amenities).map((name, index) => {
return (
<label key={index}>
<input
type="checkbox"
checked={resort.amenities[name]}
/>
{name}
</label>
);
});
Navoneel Talukdar
2021-01-04
当您使用
Object.keys()
时,您实际上是在创建一个键数组,但您无权访问这些值,例如:
console.log(Object.keys(resort.amenities)) ///[tv,reservation,moderate_noise]
而要访问这些值,您必须使用
Object.values()
console.log(Object.values(resort.amenities)) ///[false,false,true]
而对于您的代码,当使用
reduce
Object.keys(resort.amenities).reduce((result, key) => {
console.log(result) ///tv , undefined
}
因此,它会显示错误
TypeError: Cannot read property 'tv' of undefined
我不明白为什么您要将其转换为数组,而它可以直接使用!
我建议这样做
<div className="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="tv"
defaultChecked={resort ?resort.amenities.tv === true :false}
id="tv" value={true} ref={register} />
<label class="form-check-label" for="tv">TV</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="reservation"
defaultChecked={resort ?resort.amenities.reservation === true :false}
id="reservation" value={true} ref={register}/>
<label class="form-check-label" for="reservation">Reservation</label>
</div>
zahra zamani
2021-01-04