I am building a react native apps and there's a feature to change user's profile picture. And I use camera from expo to take a new profile picture, since I built my react native apps using crna.
I tried the tutorial in this following snippet.
_takePhoto = async () => {
const {
status: cameraPerm
} = await Permissions.askAsync(Permissions.CAMERA);
const {
status: cameraRollPerm
} = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (cameraPerm === 'granted' && cameraRollPerm === 'granted') {
let pickerResult = await ImagePicker.launchCameraAsync({
allowsEditing: true,
aspect: [4, 3],
});
this._handleImagePicked(pickerResult);
}
};
_pickImage = async () => {
const {
status: cameraRollPerm
} = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (cameraRollPerm === 'granted') {
let pickerResult = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3],
});
this._handleImagePicked(pickerResult);
}
};
_handleImagePicked = async pickerResult => {
let uploadResponse, uploadResult;
try {
this.setState({
uploading: true,
});
if (!pickerResult.cancelled) {
uploadResponse = await uploadImageAsync(pickerResult.uri);
uploadResult = await uploadResponse.json();
this.setState({
picture_profile: uploadResult.location
});
}
}
catch (e) {
console.log({ uploadResponse });
console.log({ uploadResult });
console.log({ e });
Alert.alert('Upload failed, sorry :(');
} finally {
this.setState({
uploading: false,
});
}
};
async function uploadImageAsync(uri){
let apiUrl= `someURL`;
let uriParts = uri.split('.');
let fileType = uriParts[uriParts.length - 1];
let formData = new FormData();
formData.append('photo', {
uri,
name:`photo.${fileType}`,
type: `picture_profile/${fileType}`,
});
//update_password
let option ={
method: 'POST',
body: formData,
headers: {
Authorization: token,
'content-type': 'multipart/form-data',
},
};
return fetch(apiUrl, option);
}
But I failed to save the picture to API. Also I got this error message when I try to upload a picture.
Possible Unhandled Promise Rejection (id:2): TypeError this._handleImagePicked is not a function
Can anyone please help me what to do? Thank you in advance.
Related
While trying to upload a file I ran into an issue on iOS, the code works fine on android. After a bit of googling, I found that it is a known issue in react-native iOS and has a bug report submitted. This is the issue. I want to know if there is any other way to upload files on iOS. Below is the snippet of code I'm using. Please let me know if there is something that can be done.
const resp = await fetch(uploadUrl, {
method: 'POST',
headers: {
'content-type': 'multipart/form-data',
},
body: file, // file is File type
});
You can something like below code snippet
function uploadProfileImage(image, token) {
const url = ServiceUrls.UPLOAD_PROFILE_IMAGE
return uploadResourceWithPost({
url,
authToken: token,
formData: createFormData(image),
})
}
const createFormData = (data) => {
const form = new FormData()
form.append('file', {
uri: Platform.OS === 'android' ? data.uri : data.uri.replace('file://', ''),
type: 'image/jpeg',
name: 'image.jpg',
})
return form
}
const uploadResourceWithPost = ({ url, authToken, formData }) => {
return handleResponse(axios.post(url, formData, defaultUploadOptions(authToken)))
}
const defaultUploadOptions = (authToken) => ({
timeout,
headers: {
'X-Auth-Token': authToken,
'Content-Type': 'multipart/form-data',
},
})
const handleResponse = (responsePromise) => {
return NetInfo.fetch().then((state) => {
if (state.isConnected) {
return responsePromise
.then((response) => {
return ResponseService.parseSuccess(response)
})
.catch((error) => {
return ResponseService.parseError(error)
})
}
return {
ok: false,
message: 'Check your network connection and try again.',
status: 408,
}
})
}
const parseSuccess = ({ data, headers }) => ({ ...data, headers, ok: true })
const parseError = ({ response }) => {
let message = 'Check your network connection and try again.'
let status = 408
if (response && response.data) {
const { data } = response
message = data.message
status = data.code
}
return { status, message }
}
im trying to upload an image to AWS Presigned url. I can get presigned url then i can upload an image from Postman, but i try to send from React Native application, just uri info is sent (content://media/external/images/media/108721). I tried a lot of thing but i cant do it. Could you help me please?
I am using react-native-image-picker to select an image.
showImagePicker = () => {
const options = {
title: 'Profile Picture',
storageOptions: {
skipBackup: true,
path: 'images',
base64: true,
},
};
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 {
const source = { uri: response.uri };
const avatarData = response;
let presignedUrl = "mypresignedurl";
const xhr = new XMLHttpRequest()
xhr.open('PUT', presignedUrl)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('Image successfully uploaded to S3')
} else {
console.log('Error while sending the image to S3', xhr.responseText)
}
}
}
xhr.setRequestHeader('Content-Type', response.type)
xhr.setRequestHeader('content-lenght', response.fileSize)
xhr.send(response.uri);
this.setState({
avatarSource: source,
avatarData: avatarData,
imageModalVisibilty: true
});
}
});
}
I saw many example like this but i just only send uri string.
I solved this issue with another way. I had to get blob data :)
export const getBlob = async (fileUri) => {
const resp = await fetch(fileUri);
const imageBody = await resp.blob();
return imageBody;
};
export const uploadImageNew = async (uploadUrl, data) => {
const imageBody = await getBlob(data);
return fetch(uploadUrl, {
method: "PUT",
body: imageBody,
});
};
reference
i'm implementing push notifications in my app and i've the following proccess:
Device receive the notification > the user tap on notification > navigate to specific screen.
Searching in the web, i didn't find anything about it.
So, i've tried to implement a listener on receive the notification, but no success.
const _handleReceivedNotification = (notification: Notification) => {
const { data } = notification.request.content;
const { request } = notification;
console.log(data, request); // notification.request.content.data object has '{ screen: "Supply/Order/ApproveOrderDetail/712177" }'
try {
props.navigation.navigate("Supply", {
screen: "Order",
param: { screen: "ApproveOrderDetail", param: { id: data.id } },
});
} catch (error) {
console.error(error);
}
};
useEffect(() => {
registerForPushNotificationsAsync();
const subscription = Notifications.addNotificationReceivedListener(
_handleReceivedNotification
);
return () => {
subscription.remove();
console.log("subscribed");
};
}, []);
Has anyone implemented this feature?
I recommend using react-native-firebase libraries in your application. This way, you can take the actions you want when your notification is triggered with the code snippet below.
import firebase from '#react-native-firebase/app'
import '#react-native-firebase/messaging'
firebase.messaging().onNotificationOpenedApp((remoteMessage) => {
if (remoteMessage) {
// console.log('onNotificationOpenedApp ', remoteMessage)
}
})
If you use Expo, in Expo Doc u have an overview on how to use expo push (with a generate token by expo, u push one time with json like that :
{
"to": "ExponentPushToken[YOUR_EXPO_PUSH_TOKEN]",
"badge": 1,
"body": "You've got mail"
},
),
and it sending directly on IOS(apns) or Android(Firebase)
Outside your class :
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
In your init function (componentDidMount), set notification:
import * as Permissions from "expo-permissions";
import * as Notifications from "expo-notifications";
Notifications.addNotificationReceivedListener(this._handleNotification);
Notifications.addNotificationResponseReceivedListener(this._handleNotificationResponse);
//Push Notification init
await this.registerForPushNotificationsAsync();
registerForPushNotificationAsync()
async registerForPushNotificationsAsync() {
if (Constants.isDevice) {
const { status: existingStatus } = await Permissions.getAsync(Permissions.NOTIFICATIONS);
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
let tokenPush = this.setAndFormatNotificationPushOnBdd();
this.setState({ expoPushToken: tokenPush });
} else {
alert('Must use physical device for Push Notifications');
}
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
};
Other functions :
_handleNotification = notification => {
this.setState({ notification: notification });
};
_handleNotificationResponse = response => {
console.log(response);
};
I just show you my Bdd save :
async setAndFormatNotificationPushOnBdd(){
try {
const tokenPush = await Notifications.getExpoPushTokenAsync();
let token = await AsyncStorage.getItem('token');
//On test le token et le régénère si besoin avec cette fonction
let validToken = await refreshToken(token);
//Si le retour n'est pas valide, on déconnecte l'utilisateur
if (!validToken) this.props.navigation.navigate('Disconnect');
let userInfo = await AsyncStorage.getItem('userInfo');
let userSession = await AsyncStorage.getItem('userSession');
let parsedUserSession = JSON.parse(userSession);
let tokenFormated = tokenPush.data;
await setNotificationPushId(parsedUserSession.user.n, tokenFormated, token,parsedUserSession)
return tokenFormated;
}catch (e) {
}
}
I am trying to upload image via axios to an API but I have issues the server sends no response at all no error this is the code
image picker
const showImage = () => {
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
setIsImageEdit(false);
} else if (response.error) {
} else if (response.customButton) {
} else {
const source = response;
setUserImage({
fileLink: source.uri,
});
setUploadImageFile(source.uri);
}
});
};
and code for upload via axios
setActivity(true);
const token = await getToken();
if (uploadImageFile) {
const uploadUri =
Platform.OS === 'ios'
? uploadImageFile.replace('file://', '')
: uploadImageFile;
const data = new FormData();
data.append('file', {
uri: uploadImageFile,
name: 'file',
type: 'image/jpg',
});
console.log(uploadImageFile);
console.log(data);
Axios.post('http://capi.beebl.io/user/image', data, {
headers: {
Authorization: token,
'Content-Type': 'multipart/form-data',
},
})
.then((res) => {
console.log(res);
setActivity(false);
})
.catch((err) => {
console.log(err);
setActivity(false);
});
there is no error displayed the activity indicator goes on and one and no response
I am uploading the image via postman and everything is good it uploads
try instead of uploadImageFile.replace('file://', '') this: uploadImageFile.replace('file:', '')
Good day! I have this function of AsyncStorage that gets an item of a token. I used with ApolloClient to process the token but when I test it first, it seems to have an error with what will I get by AsyncStorage function.
export function jwtLogin(data) {
return async dispatch => {
const userData = {
email: data.email,
password: data.password,
};
console.log(userData);
const client = new ApolloClient({
link: new HttpLink({
uri: API_URL,
}),
cache: new InMemoryCache(),
});
client
.mutate({
mutation: loginUser,
variables: {
email: userData.email,
password: userData.password,
},
})
.then(resp => {
console.log(resp.data.tokenCreate);
console.log('Token', resp.data.tokenCreate.token);
if (resp.data.tokenCreate.token !== null) {
saveJWTTokenData(resp.data.tokenCreate.token); //from AsyncStorage save function
async function main() { //function of AsyncStorage
await AsyncStorage.getItem('jwt_token').then(item => {
return item;
});
}
console.log(main()); // returns error
Actions.push('main_loading');
} else {
const errors = resp.data.tokenCreate.errors;
{
errors.map(err => {
Alert.alert('Error.', err.message);
});
}
}
})
.catch(err => {
Alert.alert('Error.', err.message);
});
};
}
For the save storage function:
export const saveJWTTokenData = async jwt_token => AsyncStorage.setItem('jwt_token', jwt_token);
My Error Log Picture
I think your Promise is not handled correctly..
Try to add a catch after your then call like this:
.catch(err => console.log(err))
Or try to use your function like this maybe:
await getData("jwt_token")
.then(data => data)
.then(value => this.setState({ token: value })) // here it is setState but I guess you can also return
.catch(err => console.log("AsyncStorageErr: " + err));