uri在React Native中不应为空字符串

时间:2018-11-05 20:56:38

标签: javascript react-native

我正在尝试从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中,默认头像图像正确显示。我不明白我不明白这一点。如果有人可以帮助我,我将不胜感激。谢谢。

1 个答案:

答案 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状态,直到进行此更改为止,因为这样,您的个人资料组件始终具有图片组件的有效网址。