Javascript TypeError:undefined不是对象(正在计算';this.state.imagesID';)
当我试图上传图片时,我遇到了一个奇怪的错误。上传到服务器可以正常工作,但在我发现错误后立即上传。当我只上传文本时,它可以正常工作,但当我在上传后尝试使用imagesID时,它会出现此错误。有人知道我为什么会出现这个错误,以及如何修复它吗 我在upload()函数内的xhr.onreadystatechange中的“this.state.imagesID.push({key:key});”行上得到错误 我在类中输入了以下错误:Javascript TypeError:undefined不是对象(正在计算';this.state.imagesID';),javascript,react-native,react-redux,aws-sdk,Javascript,React Native,React Redux,Aws Sdk,当我试图上传图片时,我遇到了一个奇怪的错误。上传到服务器可以正常工作,但在我发现错误后立即上传。当我只上传文本时,它可以正常工作,但当我在上传后尝试使用imagesID时,它会出现此错误。有人知道我为什么会出现这个错误,以及如何修复它吗 我在upload()函数内的xhr.onreadystatechange中的“this.state.imagesID.push({key:key});”行上得到错误 我在类中输入了以下错误: 'use strict'; import React, { Comp
'use strict';
import React, { Component } from 'react';
import {
Image,
Text,
TextInput,
Keyboard,
TouchableOpacity,
TouchableHighlight,
TouchableNativeFeedback,
View,
ScrollView,
Modal,
Navigator,
StyleSheet,
Dimensions,
NativeModules
} from 'react-native';
import { connect } from 'react-redux';
import {newFeed} from './api/FeedAPI';
import {showNewFeedPage} from './actions/NewFeedAction';
//import {Auth,ImgOps,Conf,Rs,Rpc} from 'react-native-qiniu';
import ImagePicker from 'react-native-image-crop-picker';
import Md5 from './util/Md5';
import KeyboardSpacer from 'react-native-keyboard-spacer';
import URLConf from './api/URLConf';
import {getToken} from './util/Secret';
import Secret from './util/Secret';
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
const margin = 20;
const imgInterval = 5;
const imgCountLimit = 9;
const textLengthLimit = 140;
const PRE_URL = URLConf.API_HOST + '/psu/';
const PUT_PRE_URL = PRE_URL + 'put';
const GET_PRE_URL = PRE_URL + 'get';
class NewFeed extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
images: [],
imagesID: [], //上传图片返回的 hash id
tags: [], //已经添加的tag
tag: '', //正在输入的tag
tagCountLimit: 5,
uploadAlready: false,
animated: true,
modalVisible: true,
transparent: false,
};
}
cancle() {
this.props.showNewFeedPage(false);
this.props.callback();
}
pickMultiple() {
ImagePicker.openPicker({
multiple: true,
maxFiles: imgCountLimit - this.state.images.length,
}).then(images => {
var newImages = this.state.images;
images.map((i, index) => {
console.log('received image', i);
newImages.push({uri: i.path, width: i.width, height: i.height, mime: i.mime, index: index});
});
this.setState({
images: newImages,
});
}).catch(e => {});
}
genId(){//Microscopic chance that the ID generated is one that already exists, but can plan for that later
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
}).toUpperCase();
}
upload() {//NEW UPLOAD!
if(this.state.images !== null && this.state.images.length != 0) {
//let formData = new FormData();
for(let img of this.state.images) {
let key = this.genId()+'.'+img.mime.replace('image/','');
console.log('img upload key:'+key);
console.log('img.mime: ' + img.mime);
let formData = {
key: key,
};
//var psu = "";
//First get a presigned URL from the server
//console.log('call back fun: ' +callback);
console.log('getting a presigned url')
getToken((token) => {
var path = PUT_PRE_URL+ "/"+ key;
var sign = Md5.hex_md5(path.replace(URLConf.APP_SERVER_HOST, '') + '?ts=123456&'+Secret.secret);
console.log('sign:' + sign);
var url = path+'?ts=123456&sign=' + sign;
console.log("url: " + url);
var options = {
//method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Auth-Token':token,
}//,
//body: encodeURI(JSON.stringify({objectKey: key}), 'utf-8')
};
console.log('[GET] ' + url);
fetch(url, options)
.then((response) => response.json())
.then((responseData) => {
console.log('[RTN] '+responseData);
console.log('[RTN] json stringified: ' + JSON.stringify(responseData));
var psu=responseData.data.url;
console.log('PSU: ' + psu);
if(psu !== null){
//then once you have presigned url, upload the image
const xhr = new XMLHttpRequest();
xhr.open('PUT', psu);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('Image successfully uploaded to S3');
console.log(key+' upload success');
this.state.imagesID.push({key:key });
if(this.state.imagesID.length == this.state.images.length) {
newFeed(this.state.text, this.state.imagesID, this.state.tags, (result, id) => {
if(result) {
this.clearState();
}
});
}
} else {
console.log('Error while sending the image to S3');
console.log('XHR ResponseText: ' + xhr.responseText);
}
}
}
console.log("image uri: " + img.uri);
xhr.setRequestHeader('Content-Type', img.mime);//'image/jpeg'
xhr.send({ uri: img.uri, type: img.mime, name: key});//name: 'myimage.jpg'})
}
})
.done();
});
// Rpc.uploadFile(img.uri, uptoken, formData).then(
// (responseData) => {
// if(responseData.status == 200) {
// console.log(key+' upload success');
// this.state.imagesID.push({key:key });
// if(this.state.imagesID.length == this.state.images.length) {
// newFeed(this.state.text, this.state.imagesID, this.state.tags, (result, id) => {
// if(result) {
// this.clearState();
// }
// });
// }
// }
// }
// );
}
this.cancle();
} else {
newFeed(this.state.text, '', this.state.tags, (result, id) => {
if(result) {
this.clearState();
}
});
this.cancle();
}
}
clearState() {
this.setState({
text: '',
images: [],
imagesID: [], //上传图片返回的 hash id
tags: [], //已经添加的tag
tag: '', //正在输入的tag
uploadAlready: false,
});
}
delImg(index) {
this.state.images.splice(index, 1);
}
renderImgsPicked() {
var imgViews = [];
if(this.state.images !== null && this.state.images.length != 0) {
for(let img of this.state.images) {
imgViews.push(<View style={styles.imgWrapper}>
{/* <Text style={styles.delIcon} onPress={this.delImg(img.index)}>x</Text> */}
<Image style={styles.img} source={img} />
</View>
);
}
}
if(this.state.images.length < imgCountLimit) {
imgViews.push(<View style={styles.imgWrapper}>
{/* <Text style={styles.delIcon} onPress={this.delImg(img.index)}>x</Text> */}
<TouchableOpacity onPress={()=>this.pickMultiple()}>
<Image style={styles.img} source={require('./imgs/pickBtn.png')} />
</TouchableOpacity>
</View>);
}
//this.upload();
return imgViews || <View/>;
}
send() {
this.upload();
}
checkTagInput(tag) {
//empty check
if(tag.indexOf(' ') == 0) return;
//end input with blank space
//TODO: ALSO ALLOW END INPUT WITH PRESSING ENTER(RETURN)
if(tag.indexOf(' ') > 0) {
tag = tag.replace(/(^\s*)|(\s*$)/g,"");
console.log('['+tag+']');
for(let i in this.state.tags) {
if(this.state.tags[i] == tag) {
return;
}
}
this.state.tags.push(tag);
this.setState({tag: ''});
} else {
this.setState({tag: tag});
}
//console.log('['+tag+']');
}
delTag(tag) {
console.log('del ' + tag);
var tags = this.state.tags;
for(let i in tags) {
if(tags[i] == tag) {
tags.splice(i,1);
break;
}
}
this.setState({tags: tags});
}
renderTags() {
var tagViews = [];
for(let i in this.state.tags) {
tagViews.push(<TouchableOpacity style={styles.tag} onPress={() => this.delTag(this.state.tags[i])}>
<Text style={{color: '#9B9B9B'}}>{this.state.tags[i]} X</Text>
</TouchableOpacity>);
}
return tagViews;
}
render() {
const {newFeedPageVisible} = this.props;
var modalBackgroundStyle = {
backgroundColor: this.state.transparent ? 'rgba(0, 0, 0, 0.5)' : '#f5fcff',
};
var innerContainerTransparentStyle = this.state.transparent
? {backgroundColor: '#fff', padding: 20}
: null;
return (
//<View style={styles.container}>
<Modal
animationType={"slide"}
transparent={this.state.transparent}
visible={newFeedPageVisible}>
<View style={styles.nav}>
<View style={styles.cancleBtn}>
<Text onPress={()=>this.cancle()}>cancel</Text>
</View>
<View style={styles.title}><Text style={{textAlign: 'center', fontWeight: 'bold'}}>Create a post</Text></View>
<View style={styles.sendBtn}>
<TouchableOpacity onPress={()=>this.send()}>
<Text style={{textAlign: 'right', color: '#00B5AD'}}>Send</Text>
</TouchableOpacity>
</View>
</View>
<ScrollView style={{ flex: 1, flexDirection: 'column'}}>
<View style={styles.input}>
<View>
<TextInput
style={styles.multiline}
placeholder="Say something..."
returnKeyType="next"
autoFocus={true}
multiline={true}
keyboardType='twitter'
maxLength = {140}
value={this.state.text}
onChangeText={(text) => this.setState({text})}
/>
<Text style={{position: 'absolute', bottom: 10, right: 20, color: '#9B9B9B'}}>{textLengthLimit-this.state.text.length}</Text>
</View>
</View>
<View style={styles.imgContainer}>
{this.renderImgsPicked()}
</View>
<View style={styles.tagsContainer}>
<View style={{flex:1, flexDirection: 'row'}}>
{/* <Image style={styles.tagIcon} source={require('./imgs/tag.png')} /> */}
<Text style={styles.tagIcon}>#</Text>
<TextInput
style={styles.tagInput}
placeholder="add tag"
returnKeyType="done"
autoFocus={false}
multiline={false}
keyboardType='twitter'
maxLength = {140}
value={this.state.tag}
onChangeText={(tag) => {this.checkTagInput(tag)}}
/>
</View>
<View style={styles.tags}>
{this.state.tags.length > 0 && this.renderTags()}
</View>
</View>
<KeyboardSpacer/>
</ScrollView>
</Modal>
//</View>
);
}
};
var styles = StyleSheet.create({
container: {
//justifyContent: 'center',
//marginTop: 70,
//padding: 20,
flex : 1,
// backgroundColor: '#ffffff',
},
innerContainer: {
borderRadius: 10,
alignItems: 'center',
},
title: {
flex: 1,
},
cancleBtn: {
width: 50,
},
sendBtn: {
width: 50,
},
wrap: {
flex: 1,
flexDirection:'column',
},
nav: {
//flex: 1,
flexDirection: 'row',
height: 70,
paddingTop: 35,
paddingLeft: 10,
paddingRight: 10,
borderBottomWidth: 0.3,
borderBottomColor: '#9B9B9B',
},
input: {
//flex:1,
//position: 'relative',
//flexDirection:'column',
},
footer: {
height: 30,
backgroundColor:'#ff99ff',
},
multiline: {
// borderWidth: 1,
// borderColor: 'black',
flex: 1,
fontSize: 18,
height: 150,
padding: 20,
paddingBottom: 40,
},
tagIcon: {
width: 20,
height: 40,
color: '#9B9B9B',
fontSize: 23,
marginLeft: 20,
},
tagsContainer: {
flex:1,
height: 100,
marginBottom: 50,
},
tagInput: {
flex:1,
height: 30,
// borderWidth: 1,
// borderColor: 'black',
width: windowWidth-margin*4,
marginRight: 20,
//marginLeft: margin,
},
tags: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
width: windowWidth-margin*2,
height: 100,
margin: margin,
marginTop: 30,
// borderWidth: 1,
// borderColor: 'black',
},
tag: {
height: 26,
marginRight: 10,
marginBottom: 5,
padding: 5,
paddingLeft: 10,
paddingRight: 10,
backgroundColor: '#F3F3F3',
// borderColor: '#adadad',
// borderWidth: 0.5,
borderRadius: 5,
},
imgContainer: {
//height: windowHeight - 70 - 150 - 30,
flexDirection: 'row',
flexWrap: 'wrap',
paddingTop: 0,
marginLeft: margin,
marginBottom: 20,
},
imgWrapper: {
position: 'relative',
width: (windowWidth-margin*2-imgInterval*2) / 3,
height:(windowWidth-margin*2-imgInterval*2) / 3,
marginBottom: imgInterval,
marginRight: imgInterval,
},
img: {
width: (windowWidth-margin*2-imgInterval*2) / 3,
height:(windowWidth-margin*2-imgInterval*2) / 3,
marginBottom: imgInterval,
marginRight: imgInterval,
resizeMode: 'cover',
},
delIcon: {
position: 'absolute',
top:0,
right: 0,
zIndex: 1,
backgroundColor: 'rgba(0,0,0,0)',
}
});
export default connect((state) => ({
newFeedPageVisible: state.showNewFeedPage.newFeedPageVisible,
}), (dispatch) => ({
showNewFeedPage: (flag) => dispatch(showNewFeedPage(flag)),
}))(NewFeed)
“严格使用”;
从“React”导入React,{Component};
进口{
形象,,
文本,
文本输入,
键盘
可触摸不透明度,
触控高光,
可触摸的本地反馈,
看法
滚动视图,
情态动词
领航员,
样式表,
尺寸,
本机模块
}从“反应本机”;
从'react redux'导入{connect};
从“./api/FeedAPI”导入{newFeed};
从“./actions/NewFeedAction”导入{showNewFeedPage};
//从'react native qiniu'导入{Auth,ImgOps,Conf,Rs,Rpc};
从“react native image crop picker”导入ImagePicker;
从“/util/Md5”导入Md5;
从“react native keyboard spacer”导入键盘间隔符;
从“./api/URLConf”导入URLConf;
从“/util/Secret”导入{getToken};
从“/util/Secret”导入机密;
const windowWidth=Dimensions.get('window').width;
const windowHeight=Dimensions.get('window').height;
常数裕度=20;
常数imgInterval=5;
常数imgCountLimit=9;
const textLengthLimit=140;
const PRE_URL=URLConf.API_HOST+/psu/;
const PUT_PRE_URL=PRE_URL+“PUT”;
const GET_PRE_URL=PRE_URL+“GET”;
类NewFeed扩展组件{
建造师(道具){
超级(道具);
此.state={
文本:“”,
图像:[],
imagesID:[]//上传图片返回的 散列id
标签:[]//已经添加的标签
标记:“”//正在输入的标签
tagCountLimit:5,
已上载:false,
是的,
真的,
透明:假,
};
}
cancle(){
this.props.showNewFeedPage(false);
this.props.callback();
}
pickMultiple(){
ImagePicker.openPicker({
多重:对,
maxFiles:imgCountLimit-this.state.images.length,
})。然后(图像=>{
var newImages=this.state.images;
images.map((i,索引)=>{
console.log('received image',i);
push({uri:i.path,width:i.width,height:i.height,mime:i.mime,index:index});
});
这是我的国家({
图片:新图片,
});
}).catch(e=>{});
}
genId(){//生成的ID可能已经存在,但可以在以后计划
返回“xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx”。替换(/[xy]/g,函数(c){
var r=Math.random()*16 | 0,
v=c=='x'?r:(r&0x3 | 0x8);
返回v.toString(16);
}).toUpperCase();
}
上传(){//新上传!
if(this.state.images!==null&&this.state.images.length!=0){
//设formData=new formData();
for(让img知道这个.state.images){
让key=this.genId()+'.+img.mime.replace('image/','');
console.log('img upload key:'+key);
log('img.mime:'+img.mime);
设formData={
钥匙:钥匙,
};
//var psu=“”;
//首先从服务器获取一个预先签名的URL
//log('callbackfun:'+callback);
log('获取预先签名的url')
getToken((令牌)=>{
var path=PUT_PRE_URL+“/”+键;
var sign=Md5.hex_Md5(path.replace(URLConf.APP_SERVER_HOST.)+'?ts=123456&'+Secret.Secret);
console.log('sign:'+sign);
var url=path+'-ts=123456&sign='+sign;
日志(“url:+url”);
变量选项={
//方法:“POST”,
标题:{
“接受”:“应用程序/json”,
“内容类型”:“应用程序/json”,
“X-Auth-Token”:标记,
}//,
//正文:encodeURI(JSON.stringify({objectKey:key}),'utf-8')
};
log('[GET]'+url);
获取(url、选项)
.then((response)=>response.json())
.然后((响应数据)=>{
console.log('[RTN]'+responseData);
log('[RTN]json字符串化:'+json.stringify(responseData));
var psu=responseData.data.url;
console.log('PSU:'+PSU);
如果(psu!==null){
//然后,一旦你预先签署了url,上传图片
const xhr=new XMLHttpRequest();
xhr.打开('PUT',psu);
xhr.onreadystatechange=函数(){
if(xhr.readyState==4){
如果(xhr.status==200){
log('图像成功上传到S3');
console.log(key+'upload success');
this.state.imagesID.push({key:key});
if(this.state.imagesID.length==this.state.images.length){
newFeed(this.state.text,this.state.imagesID,this.state.tags,(结果,id)=>{
如果(结果){
this.clearState();
}
});
}
}否则{
log('将映像发送到S3时出错');
log('XHR-ResponseText:'+XHR.ResponseText);
}
}
}
log(“图像uri:+img.uri”);
xhr.setRequestHeader('Content-Type',img.mime);//'image/jpeg'
send({uri:img.uri,type:img.mime,name:key});//name:'myimage.jpg'})