React Native - Network request failed when uploading image second time - react-native

I have found what seems to be a bug on Android. I have not tested it on IOS.
updateProfilePhoto() is a redux thunk that just sends a PUT request to my node server.
The problem is this, I can upload an image to my node server using fetch. The image is received and saved successfully on the server. If I wait for about 1 second and the upload another image, it goes through successfully. However, if I upload an image and then upload another immediately after the first one goes through, I get the error 'Network request failed' and the second image will not be received on the server.
It seems to me that I cannot constantly upload images back to back really quickly, one will go through, the next one will fail and the next will go through... and so on.
I am testing on an Android Emulator. API level 30. I have not tested on a real device yet, I will try that when I'm able to.
The error happens for the built-in fetch() and XMLHttpRequest. Both behave the same. On XMLHttpRequest I can check the progress and it says 100% and then fails with xhr.status equal to 0.
I need a sure fire way to upload an image to my server without it failing for no reason. I can add a delay of something like 500ms between uploads and show the user that it's loading but that's a silly way to resolve the issue. I can't find out why the upload fails on the second try.
const onSelectProfileImage = (pickerResponse: ImagePickerResponse) =>
{
const uri = pickerResponse?.assets && pickerResponse.assets[0].uri;
const name = pickerResponse?.assets && pickerResponse.assets[0].fileName;
const type = pickerResponse?.assets && pickerResponse.assets[0].type;
if(uri)
{
const photo = new FormData();
photo.append('photo', {name,type,uri});
dispatch(updateProfilePhoto({photo, uri, user_id: id, headers: {...headers,"content-type": "multipart/form-data"}}))
}
}

Related

React Native - console.log and network commands are not working

I've a strange problem in app I'm currently coding.
Here is the story of the app :
I've used React Native's ScrollView as a horizontal slider,
I display maximum 5~6 slides so I don't need to use FlatList for this.
Slides are actually records coming from the database so actually they are some dynamic components
and slider works as expected.
In every slide, there are also are some option buttons (Touchables) to send data to the server.
When the user presses a button app is opening a modal window to confirm and then sending some data to server.
Until now all is okay.
The Problem :
But in some slides of the slider I'm having a strange problem :
"console.log" commands and also network commands to send data to server is not working.
On the screen, I see Buttons(Touchables) are working and also the modal I've coded is also appearing & disappearing according to the state variables. But somehow console.log commands and also network commands are not even executed. Since I can't log anything it's also hard to understand the problem.
Is there anyone had a similar problem ?
Thanks
I've finally solved this problem, wanted to share my experience here.
In the app I was making post requests to the backend with Axios,
but I wasn't interested in the result of this post requests,
they were just log records so the result of backend calls weren't important.
So I didn't use any "await" command or didn't code anything like Promise.then / catch,
just posted with Axios and scrolled to another slide in my app without waiting for the backend.
After the 8th Axios post, app started not to work.
It seems like working .. touchable effects , modals even navigation works
but nothing else was working. Event console.log commands weren't working.
It's an interesting behavior of React Native , but I've understood the situation after reading the blog below :
https://medium.com/#rotemmiz/react-native-internals-a-wider-picture-part-1-messagequeue-js-thread-7894a7cba868#
Basic reason was that in the backend (NodeJS) I didn't return any response,
there wasn't any command like res.send("success") .. so frontend React Native app was waiting for the response.. event if I didn't use any await or Promise it was still trying to get the response and after the 7-8 call it was blocking the main thread.
If there is a way to configure Axios not to wait for the backend to answer for the post request, please write here.

React native async await white screen

I can't seem to find any answers online about this, but has anyone ever run into a problem with asynchronous functions causing a white screen on install?
I know the async await part of this code is causing the issue:
async syncData(){
await fetchSomeData()
navigate("to my first page");
{
The fetchSomeData() function fetches data from a url and returns a promise.
The app starts in a loading page where the above fetching is. It works fine when I don't have async await, but it doesn't wait for the data to finish fetching before navigating. The weird thing to me is that this only happens on the first install of the app.
edit:
I should try and clarify. The async await works in the sense that it waits properly for the function fetchSomeData() to do its thing. And when I build locally (with starting a metro server and debugging the app on my phone), the app works as intended. But when I build an APK, the async await in this section causes the app to crash and display a white screen (but only after the first install). If I remove the async await, it won't cause a white screen, but obviously, it doesn't wait for the data to fetch.

React native callkeep incoming call expiration time

I'm using callkeep to show an incoming call screen when a VoIP push notification is triggered. What I want to accomplish, is to ring the user for just 20 seconds. In case the user never answers, the incoming call screen should just disappear. How can I do that with callkeep?
Should it be modified in the javascript code or in the AppDelegate?
There's a solution, which is done on front end part.
First of all, run
npm i react-native-background-timer
This will help you run scheduled tasks when the app is closed.
Then, you will need to add the listener:
RNCallKeep.addEventListener("didDisplayIncomingCall", onIncomingCallDisplayed);
Which is fired when call is displayed.
And then implement it like this:
const onIncomingCallDisplayed = ({callUUID, handle, fromPushKit, payload,}) => {
BackgroundTimer.setTimeout(() => {
RNCallKeep.endAllCalls();
}, 120000);
};
Where 120000 is time in milliseconds when you want to end the call.
You could also add a backend request to notify your server that the call is rejected.

How to Upload Image From React Native To Express Server?

I am trying to upload a photo from an ios phone to an express server and I cannot seem to send the file to the server correctly. I am using react-native-image-picker and that gives me access to the photo's uri (location on the mobile phone). I am then trying to send that to the server like this:
const data = new FormData();
data.append('name', 'testName');
data.append('photo', {
uri: imageUriString,
type: 'image/jpeg',
name: 'testPhotoName'
});
I am then making a post request to the server with the body of the request being data.
The problem is that on the server side I am not getting the actual file. Instead I am getting the imageUriString which I cannot do anything with.
My req.files is undefined in the endpoint. (And I am parsing multipart/form-data so that is not the problem).
How do I upload the actual photo from React Native and receive it in req.file in Express?
I believe that you have to use var or let instead of const when using FormData. Reason being, since you are appending data to the variable, it needs to be able to change the contents of the variable's memory.

Trouble uploading media (images) to twilio programmable chat in react-native

I'm implementing programmable-chat in react-native using the npm package. Unfortunately, I'm stuck on being able to correctly upload messages with images to twilio. The twilio js documentation outlines 3 ways to create a Media Message. Sending: 1) FormData (doesn't seem applicable to me in react-native?), 2) a String, or 3) a Buffer.
I've tried many variations at this point and am stumped. I've been all over the place with both react-native-fs and react-native-fetch-blob and haven't cracked it yet.
Everything I try results in failure or in a String being uploaded. When the String is uploaded, I can complete a round trip by fetching the created Media Message, getting the the temporary url of the media attachment, manually fetching the String stored at that url, and then crafting a base64 data uri for the Image element with the fetched String. But I'm 99% sure that is 'doing it wrong'. If I do it right, Twilio should be storing an actual image for me and giving me a temporary url that I can directly feed to my Image element, right?
To sum up: I can get a base64 encoded string to be stored in twilio, but for the life of me I can't figure out how to get the image binary up there so as to be directly accessible when hitting the url it is at.
I feel like I've got to be missing something simple, but I'm out of ideas at the moment. Is there a way to get a Buffer set up in react native? Should I be trying something with FormData?
I finally figured this out. This was just a problem not knowing how to get the file into a buffer in react native. I was finally able to get this working with a combination of react-native-fs and buffer. The code looks something like:
import RNFS from 'react-native-fs'
myMethod(twilioChannelObject, filePathString) {
RNFS.readFile(filePath, 'base64').then((data) => {
var Buffer = require('buffer/').Buffer
data = Buffer.from(data, 'base64')
twilioChannelObject.sendMessage({
contentType: 'image/png',
media: data
}).then(id => {})
})
}
This probably isn't the best practice way to solve the problem, but it got it to work for me, so moving on for now.