我希望将UPLOAD_IMAGE
中的数据附加到GET_IMAGES
。无需重新渲染组件。换句话说,而不必刷新页面。
每当遵循img
时,我都会遇到类型错误
<Typography className={classes.imageTypographyTitle} variant="h4" align="center">{img.image_title}</Typography>
<Divider className={classes.imageDivider} variant="middle" />
<Image image_url={img.img_url} />
<Typography variant="h6" align="center">{img.user.username}</Typography>
<Typography variant="h6" align="center">{moment(img.created_at).calendar()}</Typography>
........
TypeError:无法读取未定义的属性“ image_title”
刷新后,我会看到新数据,并且可以添加数据,也可以看到更新后的阵列。仅当images数组为空时,才会发生类型错误。
我想将数据追加到空数组,并显示数据而无需重新渲染/刷新或任何类型错误。
我应该使用其他生命周期方法吗?因为componentWillMount
不能被调用两次,只能被调用一次。因此,鉴于该数组为空,我是否应该使用shouldComponentUpdate
之类的东西来获取初始数据?
数据结构,因为它们是数组中的现有数据。
0:{
"id": 71,
"image_title": "ii",
"img_url": "https://*********",
"created_at": "2019-06-24T02:36:48.359Z",
"updated_at": "2019-06-24T02:36:48.359Z",
"user_id": 1,
"user": {
"id": 1,
"googleId": null,
"username": "a******",
"password": "**********",
"email": "a********",
"created_at": "2019-06-23T18:57:17.253Z",
"updated_at": "2019-06-23T18:57:17.253Z"
},
"comments": []
}
减速器
import { GET_IMAGES, POST_COMMENT, DELETE_IMAGE, UPLOAD_IMAGE } from '../actions/types';
const initialState = {
images:[],
}
export default (state = initialState, action) => {
switch (action.type) {
case GET_IMAGES:
console.log(action.data);
return{
...state,
images:action.data
}
case UPLOAD_IMAGE:
const newState = {...state}
const myImages = newState.images
// console.log(myImages); // empty array
const newImage = action.newImage
console.log(newImage[0]); // gets the new uploaded image.
return {
images:[
{
id: newImage[0].id,
user:{
username:newImage[0].user.username
},
comments:{
comment_body: newImage[0].comments.comment_body
},
image_title: newImage[0].image_title,
img_url: newImage[0].img_url,
},
myImages[0] // pass the previous images if array
/// isn't empty
]
}
default:
return state;
}
}
动作
// upload image
export const uploadImage = data => {
return (dispatch) => {
Axios.post('/images/upload', data).then((response) => {
const newImage = {...response.data}
console.log(newImage);
dispatch({type:UPLOAD_IMAGE, newImage})
// history.push("/dashboard");
});
}
}
// get images
export const getImages = () => {
return async (dispatch) => {
const url = await Axios.get('/images/uploads')
const data = url.data;
dispatch({
type: GET_IMAGES,
data
})
}
}
Dashboard.js
import React, { Component } from "react";
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import ImageUploader from 'react-images-upload';
import ImageContainer from "./ImageContainer"
import {connect} from 'react-redux';
import {getImages, deleteImage, uploadImage} from '../actions/imageActions';
import dashboardStyles from '../styles/dashboardStyles';
import {withStyles} from '@material-ui/core/styles';
import {compose} from 'redux';
class Dashboard extends Component{
constructor(props){
super(props);
this.state = {
image_url: '',
description:'',
upload:false,
isComment:false,
comment_body:''
}
}
handleUpload = file => {
const data = new FormData()
const image = file[0]
// console.log(this.state.description)
// data.append('ourImage', this.state.description)
data.append('ourImage',image, this.state.description )
this.props.uploadImage(data);
this.setState({
description: ''
})
}
handleChange = (e) => {
// e.preventDefault();
this.setState({
[e.target.name]: e.target.value
})
// console.log(this.state.description)
}
componentDidMount(){
this.props.getImages();
console.log(this.props.image.images);
}
.........
{image.images.length > 0 ? (
image.images.map( (img, i) => (
<div key={i}>
<ImageContainer img={img} deleteImg={() => this.deleteImg(img.id)}/>
</div>
))
) : (
<div>
<Grid item md={8}>
<Typography>No Images yet</Typography>
</Grid>
</div>
)}
const mapStateToProps = (state) => ({
image: state.image
})
const mapDispatchToProps = (dispatch) => ({
getImages: () => dispatch(getImages()),
uploadImage: (data) => dispatch(uploadImage(data))
})
export default compose(connect(mapStateToProps, mapDispatchToProps), withStyles(dashboardStyles))(Dashboard)
图像容器
render(){
const { img, deleteImg, classes } = this.props
return(
<Grid item sm={12} md={12} className={classes.imageGridItem}>
<Paper className={classes.imageContainerPaper}>
{/* // empty image_title */}
<Typography className={classes.imageTypographyTitle} variant="h4" align="center">{img.image_title}</Typography>
<Divider className={classes.imageDivider} variant="middle" />
<Image image_url={img.img_url} />
<Typography variant="h6" align="center">{img.user.username}</Typography>
<Typography variant="h6" align="center">{moment(img.created_at).calendar()}</Typography>
........
</Grid>
)
}
}
答案 0 :(得分:1)
您需要在新状态内散布现有图像阵列。
case UPLOAD_IMAGE:
const newState = {...state}
const myImages = newState.images
// console.log(myImages); // empty array
const newImage = action.newImage
console.log(newImage[0]); // gets the new uploaded image.
return {
images:[
{
id: newImage[0].id,
user:{
username:newImage[0].user.username
},
comments:{
comment_body: newImage[0].comments.comment_body
},
image_title: newImage[0].image_title,
img_url: newImage[0].img_url,
},
...state.images
]
}
因此,您将拥有一个新状态,首先是新图像,然后是初始图像。
答案 1 :(得分:0)
修复。删除此行。
myImages[0] // pass