React Native image picker is showing image too slow after successfully uploading - react-native

after uploading image successfully the uploaded image is taking time to show ?
anyone knows anything about it?
here is my code
_onPressEdit = () => {
ImagePicker.showImagePicker(options, response => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
this._uploadImage(response.uri);
}
});
};
here is my full code
import React, {PureComponent} from 'react';
import {View, Text, Image, PermissionsAndroid, Platform} from 'react-native';
import {connect} from 'react-redux';
import ImagePicker from 'react-native-image-picker';
import styles from './styles';
import {Images, Styles, Language, Colors} from '#theme';
import {Wrapper, Input, ButtonView} from '#components';
import {TextInputField} from '#customComponents';
import {Navigator} from '#services';
import StarRating from 'react-native-star-rating';
import Header from '../Header';
import Footer from '../Footer';
import {uploadImage, editProfile} from '../../../actions/UserActions';
import {BASE_URL_PHOTO} from '../../../config/WebService';
import {selectUserData} from '../../../selectors/userSelector';
import {UserPresenter} from '../../../presenter';
import {Util} from '../../../utils';
const options = {
storageOptions: {
skipBackup: true,
path: 'images',
},
};
class Profile extends PureComponent {
constructor(props) {
super(props);
const {firstName, lastName, email, mobile, image, id} = this.props.user;
this.state = {
id,
firstName,
lastName,
email,
mobile,
image,
errors: {},
};
}
onStarRatingPress(rating) {
this.setState({
starCount: rating,
});
}
checkAllPermissions = async () => {
try {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.CAMERA,
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
]);
if (
(await PermissionsAndroid.check('android.permission.CAMERA')) &&
(await PermissionsAndroid.check('android.permission.CAMERA')) &&
(await PermissionsAndroid.check('android.permission.CAMERA'))
) {
this._onPressEdit();
return true;
} else {
console.log('all permissions denied');
return false;
}
} catch (err) {
console.warn(err);
}
};
_onPressEdit = () => {
ImagePicker.showImagePicker(options, response => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
this._uploadImage(response.uri);
}
});
};
_uploadImage = image => {
const {uploadImage} = this.props;
const {id} = this.props.user;
UserPresenter.sendUploadAvatarRequest(
uploadImage,
image,
id,
this._onSuccessImageUpload,
);
};
_onSuccessImageUpload = uri => {
this.setState({
image: uri,
});
};
_onChangeText = (key, value) => {
this.setState(
{
[key]: value,
},
() => console.log(this.state),
);
};
_validateForm = () => {
const {firstName, lastName, mobile} = this.state;
const errors = UserPresenter.getEditProfileErrors(
firstName,
lastName,
mobile,
);
this.setState({errors});
return Util.isEmpty(errors);
};
_onPressSave = () => {
const {firstName, lastName, mobile, image} = this.state;
const {id} = this.props.user;
const {editProfile} = this.props;
if (this._validateForm()) {
UserPresenter.sendEditProfileRequestStepOne(
editProfile,
id,
firstName,
lastName,
mobile,
image,
this._onSuccessSave,
);
}
};
_onSuccessSave = () => {
// Navigator.pop();
Navigator.goBack();
};
_onPressNext = () => {
if (this._validateForm()) {
Navigator.navigate('EditProfileServices', {data: this.state});
}
};
onPressFooterBtn = () => {
Navigator.navigate('EditProfileServices');
};
renderStarRating() {
const {rating} = this.props.user;
return (
<StarRating
starSize={24}
starStyle={styles.starStyle}
halfStarEnabled={true}
halfStarColor={Colors.textWhiteTwo}
emptyStarColor={Colors.textWhiteTwo}
disabled={true}
maxStars={5}
rating={rating}
selectedStar={rating => this.onStarRatingPress(rating)}
/>
);
}
renderEditFields() {
const {firstName, lastName, email, mobile, errors} = this.state;
return (
<View>
<TextInputField
title={Language.firstName}
placeholder={Language.Andrew}
value={firstName}
onChangeText={text => this._onChangeText('firstName', text)}
error={errors.firstName}
/>
<TextInputField
title={Language.lastName}
placeholder={Language.Crammer}
value={lastName}
onChangeText={text => this._onChangeText('lastName', text)}
error={errors.lastName}
/>
<TextInputField
title={Language.email}
keyboardType={'email-address'}
placeholder={Language.andrewCrammerEmail}
value={email}
onChangeText={text => this._onChangeText('email', text)}
error={errors.email}
editable={false}
/>
<TextInputField
title={Language.phone}
keyboardType={'phone-pad'}
placeholder={Language.EditProfilePhonePlaceholder}
value={mobile}
onChangeText={text => this._onChangeText('mobile', text)}
error={errors.mobileNumber}
/>
{/* <Input
label={Language.changePassword}
secureTextEntry={true}
placeholder={Language.EditProfileChangePassword}
/> */}
</View>
);
}
renderBody() {
const {rating} = this.props.user;
const {image} = this.state;
return (
<View style={Styles.paddingHorizontal}>
<View
style={[
Styles.flexDirectionRow,
Styles.alignItemsCenter,
styles.mb_30,
]}>
<View style={styles.editProfileImgWrap}>
<Image
style={styles.imgStyle}
source={{uri: `${BASE_URL_PHOTO}${image}`}}
/>
<ButtonView
isBackgroundRipple
onPress={
Platform.OS === 'android'
? this.checkAllPermissions
: this._onPressEdit
}
style={[Styles.positionAbsolute, styles.editWrap]}>
<Text style={styles.edit}>{Language.edit}</Text>
</ButtonView>
</View>
<View>
<Text style={styles.textStyle}>{Language.ProfilePicture}</Text>
</View>
</View>
<View style={styles.starStyleWrap}>
{this.renderStarRating()}
<Text style={styles.starRatingText}>{rating}</Text>
</View>
<View>{this.renderEditFields()}</View>
</View>
);
}
renderHeader() {
return <Header onPressSave={this._onPressSave} />;
}
renderFooter() {
return <Footer onPressNext={this._onPressNext} step={1} />;
}
//Render
render() {
return (
<Wrapper
header={this.renderHeader()}
footer={this.renderFooter()}
isFetching={this.props.isFetching}
isAbsolute
mainContainerStyle={Styles.paddingHorizontalNone}
isScrollView>
{this.renderBody()}
</Wrapper>
);
}
}
const mapStateToProps = state => {
return {
user: selectUserData(state.user),
isFetching: state.user.isFetching,
};
};
const actions = {uploadImage, editProfile};
export default connect(mapStateToProps, actions)(Profile);

issue solved
just compress your image size so it wont take time to appear
here is the code
const options = {
title: 'Select Picture',
storageOptions: {
skipBackup: true,
path: 'images',
},
maxWidth: 500,
maxHeight: 500,
quality: 0.5,
};
previous code was
const options = {
storageOptions: {
skipBackup: true,
path: 'images',
},
};

Related

MapboxGL React Native UserLocation Indicator do not display on map

The UserIndicator from <MapboxGL.UserLocation>, work and display fine on IOS, but with android, it's depends, it sometime work, sometime not, and i realize also, that my CameraRef.current.setCamera() is undefined when the UserIndicator doesn't display.
I tried to request with all the way i could, the location permissions like this :
React Native :
PermissionsAndroid.requestMultiple(
[PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION],
{
title: 'Give Location Permission',
message: 'App needs location permission to find your position.'
}
).then((res) => console.log(res))
MapboxGL :
if (Platform.OS == "android") {
var temp = await MapboxGL.requestAndroidLocationPermissions()
}
expo :
let { status } = await Location.requestPermissionsAsync();
all this request permissions work fine and have a output "granted" or granted : true
this is my map Component :
var Map = ({ navigation }) => {
const MapRef = React.useRef(null)
const CameraRef = React.useRef(null)
const LocationRef = React.useRef(null)
const { user, setUser } = React.useContext(UserContext)
const [data, setDATA] = React.useState([null])
const [reload, setReload] = React.useState(false)
const {location, setLocation} = React.useContext(LocationContext)
console.log(location)
var test = null;
React.useEffect(() => {
MapboxGL.setTelemetryEnabled(false);
MapboxGL.locationManager.start();
return () => {
MapboxGL.locationManager.stop();
}
// console.log(LocationRef.current)
}, [])
function handleClick() {
CameraRef.current.setCamera({
centerCoordinate: [location.coords.longitude, location.coords.latitude],
zoomLevel: 11,
animationDuration: 200,
})
}
function CenterCamera() {
if (CameraRef.current) {
CameraRef.current.setCamera({
centerCoordinate: [location.coords.longitude, location.coords.latitude],
zoomLevel: 11,
animationDuration: 2000,
})
}
}
function goTo(latitude, longitude) {
CameraRef.current.setCamera({
centerCoordinate: [longitude, latitude],
zoomLevel: 13,
animationDuration: 100,
})
}
function DisplayPings(data) {
if (data.data.length > 0) {
if (data.data[0].type_id == null) {
data.data[0].type_id = 1;
}
const val = searchInJson(data.data[0].type_id)
const features = setFeatures(val, data.data[0])
return (
<View key={data.data[0].id_activity_data}>
<MapboxGL.Images
images={{
FootBall: json[0].url,
}}
/>
<MapboxGL.ShapeSource hitbox={{ width: 20, height: 20 }} onPress={() => goTo(data.data[0].latitude, data.data[0].longitude)} id={(data.data[0].id_activity_data).toString()} shape={features}>
<MapboxGL.SymbolLayer id={(data.data[0].id_activity_data).toString()} style={{ iconImage: ['get', 'icon'] }} />
</MapboxGL.ShapeSource>
</View>
);
}
}
if (location && location.city != null && data.data) {
return (
<View style={styles.page}>
<MapboxGL.MapView onPress={() => console.log("test")} ref={(ref) => {
}
} style={styles.map} compassEnabled={false} zoomEnabled={true} >
<MapboxGL.UserLocation />
<MapboxGL.Camera ref={(ref) => {
CameraRef.current = ref
CenterCamera()
}} />
{data.data.map((data) => DisplayPings(data))}
</MapboxGL.MapView>
<ComponentsOnmap></ComponentsOnmap>
<TouchableOpacity style={styles.rondLocation} onPress={handleClick}>
<FontAwesome5 name="location-arrow" size={24} color="#434040" />
</TouchableOpacity>
<BottomSheet city={location.city} data = {data} setReload = {setReload} navigation={navigation}></BottomSheet>
</View>)
}
else
return (
<View style={styles.page}>
<MapboxGL.MapView ref={MapRef} compassEnabled={false} style={styles.map} zoomEnabled={true} >
<MapboxGL.UserLocation ref={LocationRef} />
</MapboxGL.MapView>
<ComponentsOnmap></ComponentsOnmap>
<BottomSheet city="No location" navigation={navigation}></BottomSheet>
</View>
)
}
export default Map
My condition location && location.city != null works fine, i tried without it, but the problem is still the same
My Location Context :
import React, { Component, createContext, useState, useContext } from "react";
import { Platform, PermissionsAndroid } from "react-native"
import * as Location from 'expo-location';
import MapboxGL from "#react-native-mapbox-gl/maps";
import { GetLocation } from "../API/GetLocation"
export const LocationContext = createContext();
MapboxGL.setAccessToken("Je l'ai caché bande de petit malin");
export default LocationProvider = ({ children }) => {
const [location, setLocation] = useState({ coords: [], city: null, permission: false })
const [city, SetCity] = React.useState(null)
const [coords, setCoords] = React.useState([])
React.useEffect(() => {
PermissionsAndroid.requestMultiple(
[PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION],
{
title: 'Give Location Permission',
message: 'App needs location permission to find your position.'
}
).then((res) => console.log(res))
GetLocation.then((res) => {
setLocation(res)
})
}, [])
return (
<LocationContext.Provider value={{ location, setLocation, city, SetCity, coords, setCoords }}>
{children}
</LocationContext.Provider>
)
}
My GetLocation Promise
import { useContext } from "react"
import { Platform } from "react-native"
import * as Location from 'expo-location';
import MapboxGL from "#react-native-mapbox-gl/maps";
export const GetLocation = new Promise(async (resolve, reject) => {
if (Platform.OS == "android") {
var temp = await MapboxGL.requestAndroidLocationPermissions()
}
let { status } = await Location.requestPermissionsAsync();
if (status == "granted")
Location.getCurrentPositionAsync().then((location) => {
console.log(location)
console.log("ca marche ap")
let longitude = location.coords.longitude
let latitude = location.coords.latitude
return ({ latitude, longitude })
}).then(async (coords) => Location.reverseGeocodeAsync(coords).then(async (adress) => {
resolve({ coords: coords, city: adress[0].city, granted: true })
})).catch((error) => console.log(reject(error)));
})

Invariant Violation in React Native: Text strings must be rendered within a <Text> component

I'm working on a React-Native project with REST APis, and I've currently got an invariant violation error. I've experienced this before, but I can't quite figure out what is causing it and how to fix it. If someone could point me in the right direction, I would really appreciate it! The full error is pictured below, and appears to be referencing a number of tags in the code, so I'm unsure exactly where it is originating. Thank you for reading, and thanks in advance!
The code is here:
import React, { Component } from 'react'
import { View, Text, Image, StyleSheet, FlatList} from 'react-native';
import * as Font from 'expo-font';
import styled from 'styled-components';
import dimensions from '../components/ScreenSize';
import colours from '../components/Colours';
import { Audio } from 'expo-av';
import { TouchableHighlight } from 'react-native-gesture-handler';
const client_id = {Client_ID}
const client_secret = {Client_Secret}
const item = ({item}) => (
<View style={{ flex:1, flexDirection: 'column', margin:1}}>
<TouchableHighlight onPress={() => this.fetchTracks(item.id)}>
<View>
<Text>{item.name}</Text>/>
</View>
</TouchableHighlight>
</View>
)
export default class HomeScreen extends React.Component {
state={
fontsLoaded:false,
}
async componentDidMount() {
await Font.loadAsync({
'montserrat-regular': require('../assets/fonts/Montserrat/Montserrat-Regular.ttf'),
'montserrat-light': require('../assets/fonts/Montserrat/Montserrat-Light.ttf'),
'montserrat-semibold': require('../assets/fonts/Montserrat/Montserrat-SemiBold.ttf'),
'montserrat-bold': require('../assets/fonts/Montserrat/Montserrat-Bold.ttf'),
}
).then(() => this.setState({ fontsLoaded:true }))
this.getToken();
this.setAudio();
}
constructor (props) {
super(props)
this.playbackInstance=null;
this.state = {
playing:false,
token: '',
DATA:[],
};
}
setAudio=() => {
Audio.setAudioModeAsync({
allowsRecordingIOS:false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
playThroughEarpieceAndroid: false,
});
}
componentDidCatch(error, info)
{
console.log(error, info.componentStack);
}
getToken = async() =>
{
try
{
const getspotifytoken = await fetch("https://accounts.spotify.com/api/token",
{
method:'POST',
body: `grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const spotifytoken = await getspotifytoken.json();
this.setState({
token: spotifytoken.access_token
});
console.log(this.state.token);
}
catch(err)
{
console.log("Error fetching data", err);
}
}
search = async () => {
try
{
console.log("Searching: mood")
const spotifyApiCall = await fetch(`https://api.spotify.com/v1/browse/categories/mood/playlists?`, {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${this.state.token}`,
"Content-Type":'application/json'
}
})
const spotify = await spotifyApiCall.json();
console.log("Items", spotify);
this.setState({
DATA: spotify.playlists.items,
})
}
catch (err)
{
console.log("Error fetching data", err);
}
}
fetchTracks = async (playlistId) => {
console.log('Playlist ', playlistId)
try
{
const getplaylist = await fetch(`https://api.spotify.com/v1.playlist/${playlistId}`,
{
method:'GET',
headers: {
Accept:"application/json",
Authorization:`Bearer ${this.state.token}`,
"Content-Type":"application/json"
}
});
const playlist = await getplaylist.json();
console.log('music ', playlist.tracks.items[0].preview_url);
}
catch (err)
{
console.log("Error fetching data ", err);
}
}
async _loadNewPlaybackInstance(playing, track) {
if(this.playbackInstance != null)
{
await this.playbackInstance.unloadAsync();
this.playbackInstance.setOnPlaybackStatusUpdate(null);
this.playbackInstance = null;
}
const source = {uri: track};
const initialStatus = {
shouldPlay: true,
rate: 1.0,
shouldCorrectPitch: true,
volume: 1.0,
isMuted: false
};
const {sound, status} = await Audio.Sound.createAsync(
source.initialStatus);
this.playbackInstance=sound;
this.playbackInstance.setIsLoopingAsync(false);
this.playbackInstance.playAsync();
if (this.state.selected === playlistId) {
console.log("Playing, so stop");
this.setState({selected:null});
this.playbackInstance.pauseAsync();
return;
}
this.setState({ selected:playlistId});
this._loadNewPlaybackInstance(true, playlist.tracks.items[0].preview_url);
}
render() {
if(!this.state.fontsLoaded ) {
return null
}
return (
<Container>
<Titlebar>
<Title>Music</Title>
</Titlebar>
<HeaderBar2>
<TouchableHighlight onPress={() => this.search()}>
<Header2>Playlists for your Mood</Header2>
</TouchableHighlight>
</HeaderBar2>
<View style={styles.MainContainer}>
{
this.state.DATA.length == 0 &&
<Text style={{padding:10, color:'#D3D3D3'}}/>
}
<FlatList
data = {this.state.DATA}
renderItem={item}
keyExtractor = {item.id}
numColumns={2}
extraData = {this.state}
/>
</View>
</Container>
);
}
}
I think u just have a little typo ..
check this line: <Text>{item.name}</Text>/>
change the last Text to </Text>

How to load contact details into multi select drop down in react native?

I am creating a react native app to load phone book contacts to my app using this library. I loaded contact correctly in my app. Now I wanted to load these contact details in to multi select drop down. I used react-native-multiple-select to load contact using this library. But I am not be able load contact into this library.
The UI that I need to load contact details.
This is what I tried,
import React, {Component} from 'react';
import {
View,
Text,
TouchableOpacity,
FlatList,
ActivityIndicator,
Image,
TextInput,
PermissionsAndroid,
Platform,
Modal,
TouchableHighlight,
Alert,
} from 'react-native';
import ContactsLib from 'react-native-contacts';
import {styles} from '../src/HomeTabs/ContactStyles';
import PropTypes from 'prop-types';
import {Header} from 'react-native-elements';
import MultiSelect from 'react-native-multiple-select';
//Import MultiSelect library
export class Tab2 extends Component {
constructor(props) {
super(props);
this.state = {
contactList: [],
selectedContact: [],
text: '',
isLoading: true,
show: false,
modalVisible: false,
};
this.arrayholder = [];
}
async componentDidMount() {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{
title: 'App Contact Permission',
message: 'This App needs access to your contacts ',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
this.getListOfContacts();
this.showconsole();
} else {
this.setState({isLoading: false});
this.getOtherContacts();
}
} catch (err) {
this.setState({isLoading: false});
}
} else {
ContactsLib.checkPermission((err, permission) => {
if (permission === 'denied') {
this.setState({isLoading: false});
this.getOtherContacts();
} else {
this.getListOfContacts();
}
});
}
}
// Mics Method
getOtherContacts = () => {
const {otherContactList} = this.props;
const arrFinal = [];
if (otherContactList.length > 0) {
otherContactList.map(listItem => {
arrFinal.push(listItem);
});
}
arrFinal.map((listItem, index) => {
listItem.isSelected = false;
listItem.id = index;
});
this.setState({contactList: arrFinal, isLoading: false});
this.arrayholder = arrFinal;
};
getListOfContacts = () => {
const {otherContactList} = this.props;
const arrFinal = [];
ContactsLib.getAll((err, contacts) => {
if (err) {
throw err;
}
contacts.map(listItem => {
arrFinal.push({
fullname: listItem.givenName + ' ' + listItem.familyName,
phoneNumber:
listItem.phoneNumbers.length > 0
? listItem.phoneNumbers[0].number
: '',
avatar: listItem.thumbnailPath,
});
});
if (otherContactList.length > 0) {
otherContactList.map(listItem => {
arrFinal.push(listItem);
});
}
arrFinal.map((listItem, index) => {
listItem.isSelected = false;
listItem.id = index;
});
this.setState({contactList: arrFinal, isLoading: false});
this.arrayholder = arrFinal;
});
};
getSelectedContacts = () => {
const {selectedContact} = this.state;
return selectedContact;
};
checkContact = item => {
const {onContactSelected, onContactRemove} = this.props;
let arrContact = this.state.contactList;
let arrSelected = this.state.selectedContact;
arrContact.map(listItem => {
if (listItem.id === item.id) {
listItem.isSelected = !item.isSelected;
}
});
if (item.isSelected) {
arrSelected.push(item);
if (onContactSelected) {
onContactSelected(item);
}
} else {
if (onContactRemove) {
onContactRemove(item);
}
arrSelected.splice(arrSelected.indexOf(item), 1);
}
this.setState({contactList: arrContact, selectedContact: arrSelected});
};
checkExist = item => {
const {onContactRemove} = this.props;
let arrContact = this.state.contactList;
let arrSelected = this.state.selectedContact;
arrContact.map(listItem => {
if (listItem.id === item.id) {
listItem.isSelected = false;
}
});
if (onContactRemove) {
onContactRemove(item);
}
arrSelected.splice(arrSelected.indexOf(item), 1);
this.setState({contactList: arrContact, selectedContact: arrSelected});
};
SearchFilterFunction = text => {
let newArr = [];
this.arrayholder.map(function(item) {
const itemData = item.fullname.toUpperCase();
const textData = text.toUpperCase();
if (itemData.indexOf(textData) > -1) {
newArr.push(item);
}
});
this.setState({
contactList: newArr,
text: text,
});
};
//Render Method
_renderItem = ({item}) => {
const {viewCheckMarkStyle} = this.props;
return (
<TouchableOpacity onPress={() => this.checkContact(item)}>
<View style={styles.viewContactList}>
<Image
source={
item.avatar !== ''
? {uri: item.avatar}
: require('../images/user.png')
}
style={styles.imgContactList}
/>
<View style={styles.nameContainer}>
<Text style={styles.txtContactList}>{item.fullname}</Text>
<Text style={styles.txtPhoneNumber}>{item.phoneNumber}</Text>
</View>
{item.isSelected && (
<Image
source={require('../images/check-mark.png')}
style={[styles.viewCheckMarkStyle, viewCheckMarkStyle]}
/>
)}
</View>
</TouchableOpacity>
);
};
state = {
//We will store selected item in this
selectedItems: [],
};
onSelectedItemsChange = selectedItems => {
this.setState({selectedItems});
//Set Selected Items
};
render() {
const {selectedItems} = this.state;
const {searchBgColor, searchPlaceholder, viewSepratorStyle} = this.props;
return (
<View style={styles.container}>
<MultiSelect
hideTags
items={this.contactList}
uniqueKey="id"
ref={component => {
this.multiSelect = component;
}}
onSelectedItemsChange={this.onSelectedItemsChange}
selectedItems={selectedItems}
selectText="Select Contacts"
searchInputPlaceholderText="Search Contacts..."
onChangeInput={text => console.log(text)}
tagRemoveIconColor="#ff0000"
tagBorderColor="#48d22b"
tagTextColor="#000"
selectedItemTextColor="#48d22b"
selectedItemIconColor="#48d22b"
itemTextColor="#000"
displayKey="name"
searchInputStyle={{color: '#48d22b'}}
submitButtonColor="#48d22b"
submitButtonText="Submit"
/>
<View>
{this.multiSelect &&
this.multiSelect.getSelectedItemsExt(selectedItems)}
</View>
{this.state.isLoading && (
<View style={styles.loading}>
<ActivityIndicator animating={true} size="large" color="gray" />
</View>
)}
</View>
);
}
}
Tab2.propTypes = {
otherContactList: PropTypes.array,
viewCloseStyle: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.object,
]),
viewCheckMarkStyle: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.object,
]),
sepratorStyle: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.object,
]),
viewSepratorStyle: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.object,
]),
searchBgColor: PropTypes.string,
searchPlaceholder: PropTypes.string,
onContactSelected: PropTypes.func,
onContactRemove: PropTypes.func,
};
Tab2.defaultProps = {
otherContactList: [],
viewCloseStyle: {},
viewCheckMarkStyle: {},
sepratorStyle: {},
viewSepratorStyle: {},
searchBgColor: 'rgb(202,201,207)',
searchPlaceholder: 'Search...',
onContactSelected: () => {},
onContactRemove: () => {},
};
export default Tab2;
your multiselect should be given the contacts. Try stripping out anything nonessential from your example
...
render() {
...
return (
...
<MultiSelect
items={this.state.contactList}
...
/>
...
);
}

How I can resolve this : Warning: Encountered two children with the same key, `%s`

I am new to react-native and this is not me who program this app.
Could someone help me to fix this error, I think its the flatlist who cause this because it happen only I load the page or search something on the list. I know there is a lot a question about this error but I don't find a solution for me.
Warning: Encountered two children with the same key,%s. Keys should be unique so that components maintain their identity across updates.
ContactScreen.js
import React from 'react';
import { Button, View, FlatList, Alert, StyleSheet, KeyboardAvoidingView } from 'react-native';
import { ListItem, SearchBar } from 'react-native-elements';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { Contacts } from 'expo';
import * as Api from '../rest/api';
import theme from '../styles/theme.style';
import { Contact, ContactType } from '../models/Contact';
class ContactsScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: "Contacts",
headerRight: (
<Button
onPress={() => navigation.popToTop()}
title="Déconnexion"
/>
),
}
};
constructor(props) {
super(props);
this.state = {
contacts: [],
search: '',
isFetching: false,
display_contacts: []
}
}
async componentDidMount() {
this.getContactsAsync();
}
async getContactsAsync() {
const permission = await Expo.Permissions.askAsync(Expo.Permissions.CONTACTS);
if (permission.status !== 'granted') { return; }
const contacts = await Contacts.getContactsAsync({
fields: [
Contacts.PHONE_NUMBERS,
Contacts.EMAILS,
Contacts.IMAGE
],
pageSize: 100,
pageOffset: 0,
});
const listContacts = [];
if (contacts.total > 0) {
for(var i in contacts.data) {
let contact = contacts.data[i];
let id = contact.id;
let first_name = contact.firstName;
let middle_name = contact.middleName;
let last_name = contact.lastName;
let email = "";
if ("emails" in contact && contact.emails.length > 0) {
email = contact.emails[0].email;
}
let phone = "";
if ("phoneNumbers" in contact && contact.phoneNumbers.length > 0) {
phone = contact.phoneNumbers[0].number;
}
listContacts.push(new Contact(id, first_name, middle_name, last_name, email, phone, ContactType.UP));
}
}
const soemanContacts = await Api.getContacts();
if (soemanContacts.length > 0) {
for(var i in soemanContacts) {
let contact = soemanContacts[i];
let id = contact.contact_id.toString();
let first_name = contact.contact_first_name
let last_name = contact.contact_last_name;
let email = contact.contact_email;
let phone = contact.contact_phone.toString();
listContacts.push(new Contact(id, first_name, "", last_name, email, phone, ContactType.DOWN));
}
}
listContacts.sort((a, b) => a.name.localeCompare(b.name));
this.setState({contacts: listContacts});
this.setState({ isFetching: false });
this.updateSearch(null);
}
async addContactAsync(c) {
const contact = {
[Contacts.Fields.FirstName]: c.firstName,
[Contacts.Fields.LastName]: c.lastName,
[Contacts.Fields.phoneNumbers]: [
{
'number': c.phone
},
],
[Contacts.Fields.Emails]: [
{
'email': c.email
}
]
}
const contactId = await Contacts.addContactAsync(contact);
}
onRefresh() {
this.setState({ isFetching: true }, function() { this.getContactsAsync() });
}
updateSearch = search => {
this.setState({ search });
if(!search) {
this.setState({display_contacts: this.state.contacts});
}
else {
const res = this.state.contacts.filter(contact => contact.name.toLowerCase().includes(search.toLowerCase()));
console.log(res);
this.setState({display_contacts: res});
console.log("contact display "+ this.state.display_contacts);
}
};
toggleContact(contact) {
switch(contact.type) {
case ContactType.SYNC:
break;
case ContactType.DOWN:
this.addContactAsync(contact);
break;
case ContactType.UP:
Api.addContact(contact);
break;
}
/*Alert.alert(
'Synchronisé',
contact.name + 'est déjà synchronisé'
);*/
}
renderSeparator = () => (
<View style={{ height: 0.5, backgroundColor: 'grey', marginLeft: 0 }} />
)
render() {
return (
<View style={{ flex: 1 }}>
<KeyboardAvoidingView style={{ justifyContent: 'flex-end' }} behavior="padding" enabled>
<SearchBar
platform="default"
lightTheme={true}
containerStyle={styles.searchBar}
inputStyle={styles.textInput}
placeholder="Type Here..."
onChangeText={this.updateSearch}
value={this.state.search}
clearIcon
/>
<FlatList
data={this.state.display_contacts}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
renderItem={this.renderItem}
keyExtractor={contact => contact.id}
ItemSeparatorComponent={this.renderSeparator}
ListEmptyComponent={this.renderEmptyContainer()}
/>
</KeyboardAvoidingView>
</View>
);
}
renderItem = (item) => {
const contact = item.item;
let icon_name = '';
let icon_color = 'black';
switch(contact.type) {
case ContactType.SYNC:
icon_name = 'ios-done-all';
icon_color = 'green';
break;
case ContactType.DOWN:
icon_name = 'ios-arrow-down';
break;
case ContactType.UP:
icon_name = 'ios-arrow-up';
break;
}
return (
<ListItem
onPress={ () => this.toggleContact(contact) }
roundAvatar
title={contact.name}
subtitle={contact.phone}
//avatar={{ uri: item.avatar }}
containerStyle={{ borderBottomWidth: 0 }}
rightIcon={<Ionicons name={icon_name} size={20} color={icon_color}/>}
/>
);
}
renderEmptyContainer() {
return (
<View>
</View>
)
}
}
const styles = StyleSheet.create({
searchBar: {
backgroundColor: theme.PRIMARY_COLOR
},
textInput: {
backgroundColor: theme.PRIMARY_COLOR,
color: 'white'
}
});
export default ContactsScreen;
I use react-native and expo for this application.
Just do this in you flatlist
keyExtractor={(item, index) => String(index)}
I think that your some of contact.id's are same. So you can get this warning. If you set the index number of the list in FlatList, you can't show this.
keyExtractor={(contact, index) => String(index)}
Don't build keys using the index on the fly. If you want to build keys, you should do it BEFORE render if possible.
If your contacts have a guaranteed unique id, you should use that. If they do not, you should build a key before your data is in the view using a function that produces unique keys
Example code:
// Math.random should be unique because of its seeding algorithm.
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
// after the decimal.
const keyGenerator = () => '_' + Math.random().toString(36).substr(2, 9)
// in component
key={contact.key}
Just do this in your Flatlist
keyExtractor={(id) => { id.toString(); }}
I got same error and I fixed in this case:
do not code in this way (using async) - this will repeat render many times per item (I don't know why)
Stub_Func = async () => {
const status = await Ask_Permission(...);
if(status) {
const result = await Get_Result(...);
this.setState({data: result});
}
}
componentDidMount() {
this.Stub_Func();
}
try something like this (using then):
Stub_Func = () => {
Ask_Permission(...).then(status=> {
if(status) {
Get_Result(...).then(result=> {
this.setState({data:result});
}).catch(err => {
throw(err);
});
}
}).catch(err => {
throw(err)
});
}
componentDidMount() {
this.Stub_Func();
}

How do I hash and un-hash the image in react native

I have created an app which captures images and upload to AWS s3. Currently, those are storing in the gallery. I want to hash/encrypt those images once I captured those and before uploading, I want to un-hash /decrypt those. How can I implement those in react native? I googled it but I did not find any way.
My code is,
import React, {Component} from 'react';
import {Platform, StyleSheet,Alert, Text,TouchableOpacity, View,Picker,Animated,Easing,Image, NetInfo,
Dimensions,Button,ScrollView } from 'react-native';
import ImagePicker from 'react-native-image-picker';
import DeviceInfo from 'react-native-device-info';
import { RNS3 } from 'react-native-aws3';
import Form from './Form';
const SIZE = 40;
const { width } = Dimensions.get('window');
class SecondScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
SelectedClass : '',
SelectedSection : '',
SelectedSubject : '',
serverTime : null,
saveImages : [],
testImage : [],
isConnected :false,
schoolId : 10,
userId :9,
connection_Status : "",
logout:false
}
}
getServerTime() {
fetch('http://worldclockapi.com/api/json/utc/now')
.then((response) => response.json())
.then((responseJson) => {
if (responseJson) {
this.setState({
serverTime: responseJson
})
}
console.log(responseJson);
console.log(responseJson);
})
.catch((error) => {
console.error(error);
});
}
componentDidMount = () => {
NetInfo.isConnected.addEventListener(
'connectionChange',
this._handleConnectivityChange
);
NetInfo.isConnected.fetch().done((isConnected) => {
if(isConnected == true)
{
this.setState({connection_Status : "Online"})
}
else
{
this.setState({connection_Status : "Offline"})
}
});
}
componentWillUnmount = () => {
NetInfo.isConnected.removeEventListener(
'connectionChange',
this._handleConnectivityChange
);
}
_handleConnectivityChange = (isConnected) => {
if(isConnected == true)
{
this.setState({connection_Status : 1})
}
else
{
this.setState({connection_Status : 0})
}
};
//change state of class, sesssion and subject
updateClass = (SelectedClass) => {
this.setState({ SelectedClass: SelectedClass })
}
updateSession = (SelectedSection) => {
this.setState({ SelectedSection: SelectedSection })
}
updateSubject = (SelectedSubject) => {
this.setState({ SelectedSubject: SelectedSubject })
}
takePic = () => {
if(this.state.connection_Status==="Online"){
this.getServerTime();
try{
this.setState({capturedTime:this.state.serverTime.currentFileTime+'_'+time},
() => console.log(this.state.serverTime.currentFileTime)
);
} catch (err) {
var date = new Date();
var time = date.getTime();
this.setState({capturedTime:time});
console.log("localtime")
}
}
const options = {
quality: 1.0,
maxWidth: 75,
maxHeight: 75,
base64: true,
skipProcessing: true
}
ImagePicker.launchCamera(options,(responce)=>{
this.state.testImage.push({ uri: responce.uri });
const file ={
uri : responce.uri,
name :responce.fileName,
method: 'POST',
width : 50,
height : 50,
path : responce.path,
type : responce.type,
notification: {
enabled: true
}
}
this.setState(prevState => {
// get the previous state values for the arrays
let saveImages = prevState.saveImages;
// add the values to the arrays like before
saveImages.push(file);
// return the new state
return {
saveImages
}
});
})
}
_upload=()=>{
if(this.state.connection_Status==="Online"){
const config ={
keyPrefix :'uploads/',
bucket : '***********',
region :'********',
accessKey:'************',
secretKey :'*************',
successActionStatus :201
}
this.state.saveImages.map((image) => {
RNS3.put(image,config)
.then((responce) => {
console.log(image);
});
});
if (this.state.saveImages && this.state.saveImages.length) {
Alert.alert('Successfully, saved');
this.setState({saveImages:''});
this.setState({testImage:''});
} else {
Alert.alert('No images captured');
}
} else {
Alert.alert('Upload failed. User is in offline');
}
}
signout = () => {
this.setState({
logout: true
})
}
render() {
return (
<View>
{this.state.error ? <Text>Error: {this.state.error}</Text> : null}
<View style={styles.Camera}>
<TouchableOpacity onPress={this.takePic.bind(this)}>
<Text>Take Picture</Text>
</TouchableOpacity>
</View>
<View style={styles.Send}>
<TouchableOpacity onPress={() => this._upload()}>
<Text>Send</Text>
</TouchableOpacity>
</View>
</View >
}</View>
);
}
}
const styles = StyleSheet.create({
});
export default SecondScreen;