如何解决res.data
我正在制作前端组件,它将上传用户的封面照片和头像照片这两个不同的图像。我使用 node.js 作为我的后端与 express.js。如果用户上传封面照片,后端将发送 res.send(如果图像是 coverPhoto 或 avatarPhoto,它会保护图像路径)。但是我在用户上传图像后如何上传它们时遇到问题。我习惯于不同的 useState userInfo.coverPhoto 和 userInfo.avatarPhoto。问题是在用户单击coverPhoto 然后单击avatarPhoto 后,coverPhoto 的图像src 将损坏图像。但刷新后图像就会出现。
userProfile.js
import React,{ useState,useEffect } from 'react';
import { usedispatch,useSelector } from 'react-redux';
import axios from 'axios';
import PersonIcon from '@material-ui/icons/Person';
import {
Container,Grid,Typography,TextField,Button,Modal,Backdrop,} from '@material-ui/core';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import ImageIcon from '@material-ui/icons/Image';
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
import { useForm } from 'react-hook-form';
import FormContainer from '../components/FormContainer';
import useStyles from '../styles/style';
import {
getDetailsUser,updateDetailsUser,} from '../redux/actions/userActions';
const ProfilePage = ({ history }) => {
const userDetails = useSelector((state) => state.userDetails);
const { user } = userDetails;
const userLogin = useSelector((state) => state.userLogin);
const { userData } = userLogin;
const userUpdateDetails = useSelector((state) => state.userUpdateDetails);
const { userUpdate } = userUpdateDetails;
const [userInfo,setUserInfo] = useState({
id: user._id,username: '',email: '',fullname: '',coverPhoto: '',avatarPhoto: '',about: '',mainAddress: '',country: '',city: '',zipcode: '',});
const [coverPreview,setCoverPreview] = useState('');
const [avatarPreview,setAvatarPreview] = useState('');
const [open,setopen] = useState(false);
const dispatch = usedispatch();
const classes = useStyles();
useEffect(() => {
if (!userData) {
history.push('/user/login');
} else {
if (!user || !user.username || userUpdate) {
dispatch(getDetailsUser('profile'));
// if (!userInfo.coverPhoto) {
// document.getElementById(
// 'coverPhoto-file-button'
// ).nextElementSibling.style.opacity = '0';
// }
} else {
setUserInfo(user);
}
}
},[userData,user,userUpdate,history]);
const handleClose = () => {
setopen(false);
};
const handleChange = (level) => (e) => {
e.preventDefault();
if (!level) {
setUserInfo({
...userInfo,[e.target.name]: e.target.value,});
} else {
setUserInfo({
...userInfo,[level]: {
...userInfo[level],},});
}
};
const uploadCoverPhotoHandler = async (e) => {
const imgFile = e.target.files[0];
const imgFieldName = e.target.name;
if (imgFile.type !== 'image/jpeg' && imgFile.type !== 'image/png') {
console.log('wrong format');
}
let formData = new FormData();
formData.append(imgFieldName,imgFile);
try {
await axios({
method: 'POST',url: 'http://localhost:5000/user/profile',data: formData,headers: {
'content-type': 'multipart/form-data',}).then((res) => {
if (imgFieldName === 'coverPhoto') {
setUserInfo({ coverPhoto: res.data });
} else {
setUserInfo({ avatarPhoto: res.data });
}
});
} catch (error) {
console.log(error.response);
}
};
const onSubmit = async (e) => {
dispatch(updateDetailsUser(userInfo));
setopen(true);
};
const { register,handleSubmit,errors,getValues } = useForm({
mode: 'onSubmit',reValidateMode: 'onBlur',});
return (
<FormContainer>
<Container component="div" className={classes.profileContainer}>
<Modal
className={classes.modal}
open={open}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
root: classes.modalRoot,timeout: 500,}}
>
<div className={classes.modalContainer}>
<Typography
component="h1"
variant="h5"
className={classes.promptTitle}
>
Account has been updated!
</Typography>
<Button
type="submit"
variant="contained"
className={classes.button}
onClick={handleClose}
style={{ width: '60%',marginBottom: '2.5rem' }}
>
Close
</Button>
</div>
</Modal>
<Grid item xs={12}>
<Card className={classes.userProfileCard}>
<CardContent>
<form novalidate onSubmit={handleSubmit(onSubmit)}>
<Typography
component="h1"
variant="h4"
className={classes.titleProfile}
>
<PersonIcon
style={{
position: 'relative',top: '5px',marginRight: '0.2em',}}
/>
Edit Profile
</Typography>
<Grid container spacing={2}>
<Grid item xs={6}>
<TextField
variant="outlined"
id="username"
name="username"
type="text"
label="Username"
value={userInfo && userInfo.username}
onChange={handleChange()}
fullWidth
InputLabelProps={{
classes: {
root: classes.label,focused: classes.focused,shrink: true,}}
InputProps={{
className: classes.textfield,classes: {
root: classes.cssOutlinedInput,focused: classes.cssFocused,notchedOutline: classes.notchedOutline,}}
inputRef={register({
required: 'You must provide an username.',minLength: {
value: 4,message:
'Your username must be greater than 4 characters',pattern: {
value: /^[A-Za-z0-9_]+$/i,message:
'Username may only have letters,number and underscores.',})}
/>
{errors.username && (
<span className={classes.error}>
{errors.username.message}
</span>
)}
</Grid>
<Grid item xs={6}>
<TextField
variant="outlined"
id="email"
name="email"
type="email"
label="Email"
value={userInfo && userInfo.email}
onChange={handleChange()}
fullWidth
InputLabelProps={{
classes: {
root: classes.label,}}
inputRef={register({
required: 'You must provide a email.',pattern: {
value: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/,message: 'You must provide a valid email address!',})}
/>
{errors.email && (
<span className={classes.error}>
{errors.email.message}
</span>
)}
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
id="fullname"
name="fullname"
type="text"
label="Fullname"
value={userInfo && userInfo.fullname}
onChange={handleChange()}
fullWidth
InputLabelProps={{
classes: {
root: classes.label,}}
inputRef={register({
required: 'You must provide a fullname.',minLength: {
value: 6,message:
'Your password must be greater than 6 characters',pattern: {
value: /^[A-Za-z ]+$/i,message: 'Alphabetical characters only',})}
/>
{errors.fullname && (
<span className={classes.error}>
{errors.fullname.message}
</span>
)}
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
id="mainAddress"
name="mainAddress"
type="text"
label="Address"
value={userInfo.address && userInfo.address.mainAddress}
onChange={handleChange('address')}
fullWidth
InputLabelProps={{
classes: {
root: classes.label,}}
/>
</Grid>
<Grid item xs={2}>
<TextField
variant="outlined"
id="city"
name="city"
type="text"
label="City"
value={userInfo.address && userInfo.address.city}
onChange={handleChange('address')}
fullWidth
InputLabelProps={{
classes: {
root: classes.label,}}
/>
</Grid>
<Grid item xs={2}>
<TextField
variant="outlined"
id="country"
name="country"
type="text"
label="Country"
value={userInfo.address && userInfo.address.country}
onChange={handleChange('address')}
fullWidth
InputLabelProps={{
classes: {
root: classes.label,}}
/>
</Grid>
<Grid item xs={2}>
<TextField
variant="outlined"
id="zipcode"
name="zipcode"
type="text"
label="Zipcode"
value={userInfo.address && userInfo.address.zipcode}
onChange={handleChange('address')}
fullWidth
InputLabelProps={{
shrink: true,classes: {
root: classes.label,}}
inputRef={register({
pattern: {
value: /^[0-9]+([0-9]+)?$/,message: 'Numbers only',})}
/>
{errors.zipcode && (
<span className={classes.error}>
{errors.zipcode.message}
</span>
)}
</Grid>
<Grid item xs={12}>
<Grid item xs={12}>
<TextField
variant="outlined"
id="aboutme"
name="about"
type="text"
label="About me"
value={userInfo && userInfo.about}
onChange={handleChange()}
fullWidth
multiline
rows={2}
InputLabelProps={{
classes: {
root: classes.label,}}
InputProps={{
className: classes.textfield,classes: {
root: classes.cssOutlinedInput,}}
/>
</Grid>
</Grid>
<Grid item xs={2}>
<Button
type="submit"
fullWidth
variant="contained"
className={classes.button}
>
Update
</Button>
</Grid>
</Grid>
</form>
</CardContent>
</Card>
</Grid>
<Grid item xs={12}>
<Card className={classes.userCard}>
<form id="userPhoto">
<CardContent className={classes.coverPhotoContainer}>
<CardMedia
component="img"
src={userInfo && userInfo.coverPhoto}
height="180rem"
onload="this.style.display=''"
/>
<input
accept="image/*"
id="coverPhoto-file-button"
type="file"
name="coverPhoto"
style={{ display: 'none' }}
onChange={uploadCoverPhotoHandler}
/>
<label htmlFor="coverPhoto-file-button">
<ImageIcon />
Add Cover Photo
</label>
</CardContent>
<CardContent className={classes.imgProfileContainer}>
<CardMedia
component="img"
src={userInfo && userInfo.avatarPhoto}
height="180rem"
onload="this.style.display=''"
/>
<input
accept="image/*"
id="imgProfile-file-button"
type="file"
name="avatarPhoto"
style={{ display: 'none' }}
onChange={uploadCoverPhotoHandler}
/>
<label htmlFor="imgProfile-file-button">
<AccountCircleIcon />
</label>
</CardContent>
</form>
<CardContent>
<Typography
className={classes.titleProfileUsername}
variant="h6"
component="h1"
>
{userInfo && userInfo.username}
</Typography>
<Typography
className={classes.profileAbout}
variant="body2"
component="p"
></Typography>
</CardContent>
</Card>
</Grid>
</Container>
</FormContainer>
);
};
export default ProfilePage;
错误 这将在上传头像照片后发生,封面照片中的图像将消失,但在我刷新页面后,它将再次出现。
解决方法
useState
在类组件中的作用与 this.setState
不同。
在写入 setUserInfo({ coverPhoto: res.data })
时,您从 userInfo
中删除所有其他字段。
你需要写:
setUserInfo(prevState => ({ ...prevState,coverPhoto: res.data }))
}).then((res) => {
if (imgFieldName === 'coverPhoto') {
setUserInfo(prevState => ({ ...prevState,coverPhoto: res.data }));
} else {
setUserInfo(prevState => ({ ...prevState,avatarPhoto: res.data }));
}
});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。