我正在尝试从Firebase存储或我的项目img文件夹中的默认头像渲染图像配置文件,具体取决于当前用户是否具有配置文件。虽然以下代码在我的Menu.js中完美显示了用户图像或头像图像:
import React, { Component } from 'react';
import { View, Text, Image } from 'react-native';
import { Actions } from 'react-native-router-flux';
import { Content, List, ListItem, Thumbnail } from 'native-base';
import firebase from 'firebase';
import Helpers from '../../lib/helpers';
class Menu extends Component {
constructor(props) {
super(props);
this.state = {
avatarUrl: '',
userName: '',
userLastname: '',
userEmail: '',
userBio: '',
uid: ''
};
}
async componentWillMount() {
try {
const user = await firebase.auth().currentUser;
Helpers.getImageUrl(user.uid, (imageUrl) => {
this.setState({ avatarUrl: imageUrl });
});
Helpers.getUserName(user.uid, (name) => {
this.setState({ userName: name });
});
Helpers.getUserLastname(user.uid, (lastname) => {
this.setState({ userLastname: lastname });
});
Helpers.getUserEmail(user.uid, (email) => {
this.setState({ userEmail: email });
});
Helpers.getUserBio(user.uid, (bio) => {
this.setState({ userBio: bio });
});
this.setState({ uid: user.uid });
} catch (error) {
console.log(error);
}
}
mostrarAvatar() {
if (this.state.avatarUrl) {
return (<Image
style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
source={{ uri: this.state.avatarUrl }}
/>);
}
return (<Thumbnail
source={require('../../img/avatar.png')}
large
/>);
}
mostrarNombreUsuario() {
if (this.state.userName !== '') {
return <Text style={{ color: 'white', fontSize: 15 }}>{this.state.userName}</Text>;
}
return <Text style={{ color: 'white', fontSize: 15 }}>Usuario</Text>;
}
render() {
const { userName, userLastname, userEmail, userBio, avatarUrl } = this.state;
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: '#2c3e50', justifyContent: 'center', alignItems: 'center' }}>
{this.mostrarAvatar()}
{this.mostrarNombreUsuario()}
</View>
<View style={{ flex: 2 }}>
<Content>
<List>
<ListItem onPress={() => Actions.albumList()}>
<Text>Los más escuchados</Text>
</ListItem>
<ListItem>
<Text>buscar por género</Text>
</ListItem>
<ListItem onPress={() => Actions.profile({
name: userName,
lastname: userLastname,
email: userEmail,
bio: userBio,
avatar: avatarUrl })}
>
<Text>Perfil</Text>
</ListItem>
<ListItem onPress={() => Actions.auth()}>
<Text>Cerrar sesión</Text>
</ListItem>
</List>
</Content>
</View>
</View>
);
}
}
export default Menu;
我的Profile.js中的那个不是:(请参见renderAvatar函数)
import React, { Component } from 'react';
import _ from 'lodash';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
Image,
TextInput,
Platform,
ToastAndroid,
Dimensions,
ScrollView,
Thumbnail
} from 'react-native';
import ImagePicker from 'react-native-image-picker';
import firebase from 'firebase';
import RNFetchBlob from 'react-native-fetch-blob';
import Helpers from '../../lib/helpers';
import Avatar from '../../img/avatar.png';
const ITEM_WIDTH = Dimensions.get('window').width;
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
const uploadImage = (uri, imageName, mime = 'image/jpg') => {
return new Promise((resolve, reject) => {
const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
let uploadBlob = null;
const imageRef = firebase.storage().ref('images').child(imageName);
fs.readFile(uploadUri, 'base64')
.then((data) => {
return Blob.build(data, { type: `${mime};BASE64` });
})
.then((blob) => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
return imageRef.getDownloadURL();
})
.then((url) => {
resolve(url);
})
.catch((error) => {
reject(error);
});
});
};
class Profile extends Component {
constructor(props) {
super(props);
this.state = {
imagePath: '',
name: this.props.avatar !== 'profile' ? this.props.name : '',
lastname: this.props.avatar !== 'profile' ? this.props.lastname : '',
email: this.props.avatar !== 'profile' ? this.props.email : '',
bio: this.props.avatar !== 'profile' ? this.props.bio : '',
uid: ''
};
}
async componentWillMount() {
try {
const { currentUser } = await firebase.auth();
this.setState({
uid: currentUser.uid
});
} catch (error) {
console.log(error);
}
}
openImagePicker() {
const options = {
title: 'Seleccione avatar',
storageOptions: {
skipBackup: true,
path: 'images'
}
};
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
console.log('User canceled image Picker');
} else if (response.error) {
console.log('Error' + response.error);
} else if (response.customButton) {
console.log('User tapped custom button' + response.customButton);
} else {
this.setState({
imagePath: response.uri,
imageHeight: response.height,
imageWidth: response.width
});
}
});
}
saveForm() {
const { name, lastname, email, bio, uid, imagePath } = this.state;
if (uid) {
try {
name ? Helpers.setUserName(uid, name) : null;
bio ? Helpers.setUserBio(uid, bio) : null;
email ? Helpers.setUserEmail(uid, email) : null;
lastname ? Helpers.setUserLastname(uid, lastname) : null;
imagePath ?
uploadImage(imagePath, `${uid}.jpg`)
.then((responseData) => {
Helpers.setImageUrl(uid, responseData);
})
.done()
: null;
toastMessage('¡Tu datos han sido actualizados!');
} catch (error) {
console.log(error);
}
}
}
renderAvatar() {
console.log(this.props.avatar);
if (this.props.avatar !== null) {
return (<Image
style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
source={{ uri: this.props.avatar }}
/>);
}
return (<Image
style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
source={Avatar}
/>);
}
render() {
return (
<ScrollView contentContainerStyle={{ alignItems: 'center' }} style={styles.container}>
<TouchableOpacity
onPress={this.openImagePicker.bind(this)}
style={{ marginBottom: 40, marginTop: 20 }}
>
<View style={{ alignItems: 'center' }}>
{this.renderAvatar()}
<Text style={{ color: 'white' }}>Avatar </Text>
</View>
</TouchableOpacity>
<TextInput
underlineColorAndroid='rgba(0,0,0,0)'
selectionColor="#fff"
placeholderTextColor="#ffffff"
autoCorrect={false} //we disable the autocorrect from ios or android
style={styles.textInput}
placeholder='nombres'
value={this.state.name}
onChangeText={(name) => this.setState({ name })}
/>
<TextInput
underlineColorAndroid='rgba(0,0,0,0)'
selectionColor="#fff"
placeholderTextColor="#ffffff"
autoCorrect={false} //we disable the autocorrect from ios or android
style={styles.textInput}
placeholder='apellidos'
value={this.state.lastname}
onChangeText={(lastname) => this.setState({ lastname })}
/>
<TextInput
underlineColorAndroid='rgba(0,0,0,0)'
selectionColor="#fff"
placeholderTextColor="#ffffff"
autoCorrect={false} //we disable the autocorrect from ios or android
style={styles.textInput}
type='email-address'
placeholder='email@gmail.com'
keyboardType="email-address"
autoCapitalize="none"
value={this.state.email}
onChangeText={(email) => this.setState({ email })}
/>
<TextInput
multiline={true}
numberOfLines={10}
underlineColorAndroid='rgba(0,0,0,0)'
selectionColor="#fff"
placeholderTextColor="#ffffff"
autoCorrect={false} //we disable the autocorrect from ios or android
style={styles.textArea}
placeholder='Ingresa algo sobre tí'
value={this.state.bio}
onChangeText={(bio) => this.setState({ bio })}
/>
<TouchableOpacity
style={styles.buttonStyle}
onPress={this.saveForm.bind(this)}
>
<Text style={styles.buttonText}>Guardar</Text>
</TouchableOpacity>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0277BD',
},
textInput: {
height: 40,
borderWidth: 1,
borderColor: '#cecece',
marginBottom: 20,
borderRadius: 20,
paddingHorizontal: 20,
marginHorizontal: 50,
backgroundColor: 'rgba(255, 255, 255, 0.3)',
color: '#ffffff',
width: ITEM_WIDTH - 100,
},
buttonStyle: {
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 20,
paddingVertical: 10,
width: 100,
backgroundColor: '#2D09A1',
marginHorizontal: 20,
marginTop: 20,
marginBottom: 20
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
textArea: {
height: 150,
justifyContent: 'flex-start',
textAlignVertical: 'top',
borderWidth: 1,
borderColor: '#cecece',
marginBottom: 20,
borderRadius: 20,
paddingHorizontal: 16,
backgroundColor: 'rgba(255, 255, 255, 0.3)',
color: '#ffffff',
width: ITEM_WIDTH - 150,
}
});
const toastMessage = (texto) => {
ToastAndroid.showWithGravity(
texto,
ToastAndroid.SHORT,
ToastAndroid.CENTER
);
};
export default Profile;
问题出在renderAvatar方法中:我已经以与Menu.js中相同的方式定义了该方法,并以与Menu.js中相同的方式并使用相同的图像路径返回了该方法就像在Menu.js中一样,并且Menu.js和Profile.js都位于同一目录中。但是我收到以下错误消息:“ uri不应为空字符串”。
当我刚回来时:
render() {
return (
<ScrollView contentContainerStyle={{ alignItems: 'center' }} style={styles.container}>
<TouchableOpacity
onPress={this.openImagePicker.bind(this)}
style={{ marginBottom: 40, marginTop: 20 }}
>
<View style={{ alignItems: 'center' }}>
<Image
style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
source={Avatar}
/> ...
在我的Profile.js中,默认头像图像正确显示。我不明白我不明白这一点。如果有人可以帮助我,我将不胜感激。谢谢。
答案 0 :(得分:0)
在构造函数中,您不能使用this.props.
,而必须直接使用props
,因为此时this
不可用。使用配置文件组件时,让我看看您的代码。
我认为您必须将this.props.avatar
与''
而不是null
进行比较,因为您的初始状态是。
<ListItem onPress={() => Actions.profile({
name: userName,
lastname: userLastname,
email: userEmail,
bio: userBio,
avatar: avatarUrl })}
>
您要传递''
值的null
而不是avatarUrl
。另外,您还可以使用默认头像的uri值来初始化avatarUrl
状态,直到进行此更改为止,因为这样,您的个人资料组件始终具有图片组件的有效网址。