Why is my useeffect clean up function not executing? - javascript

Why is my useeffect clean up function not executing?
"Downloaded" prints in the console, but "Cleaned up" never prints.
I need it to be called after the useeffect runs (every time) to clear up memory.
Here's my code:
useEffect(() => {
if (!downloadedFile) return;
const link = document.createElement("a");
link.href = downloadedFile.file;
link.setAttribute("download", downloadedFile.filename);
document.body.appendChild(link);
link.click();
console.log("downloaded");
return () => {
console.log("cleaned up");
link.remove();
window.URL.revokeObjectURL(downloadedFile.file);
dispatch(cleanUpAfterDownload());
};
}, [downloadedFile]);
Thanks in advance.

Related

Download multiple files in an angular application

I have an async method that retrieves the presigned URL of a selected file and a method that takes that URL and downloads the file by adding an anchor tag, assigns the URL to href and then simulates a click event. It works fine for a single file download. However, when there are multiple files selected it doesn't download all the files. I have tried other approaches such as calling fetch(), axios etc but that also results in the same issue.
Below is my code:
method in component:
`public async downloadSelectedFiles(event: Event, entitlementId: string) {
event.preventDefault();
for (const releaseFile of this.selectedReleaseFiles) {
const url = await this._softwareProductsService.getFileDownloadUrl(entitlementId, String(releaseFile.id));
await this._downloadService.downloadFile(url);
}
}`
method in service:
`public async downloadFile(url: string): Promise<void> {
const a = this._document.createElement('a');
a.download = '';
a.href = url;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
await this._delay(100);
document.body.removeChild(a);
}
private _delay(ms: number): Promise<void> {
return new Promise<void>((resolve) => {
setTimeout(resolve, ms);
});
}`
I have tried setting id of anchor tag. Waiting after click and after remove as well. Also tried 'multi-download' library. All result in same issue.
It doesn't download all the files when download button is clicked for the first time. When clicked again it works fine.
Is there a way to await on anchor tag click event?

Detect if WhatsApp is installed

Using Android or a desktop browser, please visit this WhatsApp test page and click the Send button. If WhatsApp is not installed it will show you a message.
How does the code detection on that page work? I tried the following but nothing happens.
try {
location.href = 'whatsapp://send/?phone=62812345678&text=test';
} catch (e) {
console.log(e);
}
Looking at the page, it appears that at least on Chrome, they programmatically open an iframe with the src of whatsapp://send/?phone=<number>&text=test. They then start a 1000ms timeout after which the "Looks like you don't have WhatsApp installed!" text is shown. This timeout is cancelled by an blur event handler, meaning that their check is based on your device opening WhatsApp when that URL is loaded, which blurs the window.
The function which triggers after the timeout also seems to check if the timeout took longer than 1250ms. I suspect that this handles the case where your phone's browser stops executing JS timers when it changes apps.
On IE, they use window.navigator.msLaunchUri, which accepts a noHandlerCallback.
See for yourself by opening your browser's devtools and searching for WhatsAppApiOpenUrl. On Chrome, the Search can be found from the devtools' menu:
Here's some example code.
const detectWhatsapp = (phone, text) => {
const uri = `whatsapp://send/?phone=${encodeURIComponent(
phone
)}&text=${encodeURIComponent(text)}`;
const onIE = () => {
return new Promise((resolve) => {
window.navigator.msLaunchUri(
uri,
() => resolve(true),
() => resolve(false)
);
});
};
const notOnIE = () => {
return new Promise((resolve) => {
const a =
document.getElementById("wapp-launcher") || document.createElement("a");
a.id = "wapp-launcher";
a.href = uri;
a.style.display = "none";
document.body.appendChild(a);
const start = Date.now();
const timeoutToken = setTimeout(() => {
if (Date.now() - start > 1250) {
resolve(true);
} else {
resolve(false);
}
}, 1000);
const handleBlur = () => {
clearTimeout(timeoutToken);
resolve(true);
};
window.addEventListener("blur", handleBlur);
a.click();
});
};
return window.navigator.msLaunchUri ? onIE() : notOnIE();
};
Please note that it adds an event listener each time it's called. If you're rolling this out into production, please use window.removeEventListener to remove handleBlur after the promise resolves. It also appends a DOM node into the body, if that matters to you.
Usage example:
detectWhatsapp('<your number here>', 'test').then(hasWhatsapp =>
alert(
'You ' +
(hasWhatsapp ? 'have WhatsApp' : "don't have WhatsApp")
)
)
Here my testing on Android:
Built-in Browser (Webview) and Firefox if WA installed You can use iframe to auto open WhatsApp
Chrome and Opera Need user click action
but luckily I only need this simple code to detect if whatsapp installed
document.querySelector('#openWA').addEventListener('click', function() {
var f = Date.now(),
j = setTimeout(function() {
if (Date.now() - f > 1250)
return;
alert('WA not installed')
}, 1e3);
})
<a href="whatsapp://send/?phone=62812345678&text=test" id="openWA">Send to WhatsApp</button>
<!-- Auto open on WebView and Firefox -->
<iframe id="launcher" src="whatsapp://send/?phone=62812345678&text=test" style="display: none;"></iframe>
If you have jquery, bassed on the code above if whats app does not open open a new page using whatsapp web instead of iframe launcher:
$('a[href^="whatsapp://send?"]').click(function() {
var button = this,
f = Date.now(),
j = setTimeout(function() {
if (Date.now() - f > 1025){
return;
}else{
var newLink = button.getAttribute('href').replace("whatsapp://send?", "https://web.whatsapp.com/send?");
button.setAttribute('href', newLink);
button.setAttribute('target', "_blank");
$(button).closest('div').append('<a class="hide new" href="' + newLink + '" target="_blank" ></a>');
$(button).closest('div').find('a.new')[0].click();
}
}, 1e3);
})

Download a file and reload a page once the file is downloaded [duplicate]

This question already has answers here:
Detect when user accepts to download a file
(7 answers)
Closed 3 years ago.
I am trying to download a file and then reload the page.
The issue is that this code works only when the file download is completed within a second.
If the file is any bigger the first request to download the file seems to be blocked by the second request.
javascript:
//downloads the file
function updateAndDownload() {
var link = document.createElement('a');
link.href = "updateAndDownloadFile.rails?id=$ID";
document.body.appendChild(link);
link.click();
PageReload();
}
//wait for a second and refresh the page
function PageReload() {
setTimeout(function() {
refreshPage();
}, 1000);
}
function refreshPage() {
// Close dialog.
Control.Modal.close();
// Reload.
window.location.href = "index.rails?id=" + ID
}
I expect the file to be downloaded and the page to be refreshed maybe back to back or at the same time
instead of this..
// Reload.
"window.location.href = "index.rails?id=" + ID"
use this... it works on my program
//Reload
"window.location.reload(true);"
Can you try with adding target attribute to link.
function updateAndDownload() {
var link = document.createElement('a');
link.href = "updateAndDownloadFile.rails?id=$ID";
/** Add this line **//
link.target = '_blank';
document.body.appendChild(link);
link.click();
PageReload();
}
//wait for a second and refresh the page
function PageReload() {
setTimeout(function() {
refreshPage();
}, 1000);
}
function refreshPage() {
// Close dialog.
Control.Modal.close();
// Reload.
window.location.href = "index.rails?id=" + ID
}

Why isn't video recording working in my React-app?

so I am trying to incorporate a feature into a website for a client where visitors can record video on their site and then download it/upload it onto their server.
They wish for this to be built as a react component but I just started learning react last week so I'm a tad confused however it shouldn't be too complex.
So I have the following code which works in simple html/js files, outside of react where if you run it you get a little video recording screen and you can download the recording:
I also tried including the contents of de.js into the Def class component instead of importing it but this also led to the same result.
I have tried to figure out any other better easier ways to get video recording and uploading/downloading functionality into a react-component but haven't found any. I can't quite figure out how to use the popular RecordRTC library for this. Any other simple solution would be great, I'm not bound to this way of doing this, I just need to get something that works.
Any help would be GREATLY appreciated!!!
********************************** EDIT **************************************
If I run the below code:
import React, { Component } from 'react';
import './Def.css';
class Def extends Component {
render() {
const constraints = {
"video": {
width: {
max: 400
}
},
"audio": true
};
var theStream;
var theRecorder;
var recordedChunks = [];
function startFunction() {
navigator.mediaDevices.getUserMedia(constraints)
.then(gotMedia)
.catch(e => {
console.error('getUserMedia() failed: ' + e);
});
}
function gotMedia(stream) {
theStream = stream;
var video = document.querySelector('video');
video.src = URL.createObjectURL(stream);
try {
var recorder = new MediaRecorder(stream, {
mimeType: "video/webm"
});
} catch (e) {
console.error('Exception while creating MediaRecorder: ' + e);
return;
}
theRecorder = recorder;
recorder.ondataavailable =
(event) => {
recordedChunks.push(event.data);
};
recorder.start(100);
}
function stopFile() {
theRecorder.stop();
}
function download() {
theRecorder.stop();
theStream.getTracks().forEach(track => {
track.stop();
});
var blob = new Blob(recordedChunks, {
type: "video/webm"
});
var url = URL.createObjectURL(blob);
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = url;
a.download = 'test.webm';
a.click();
// setTimeout() here is needed for Firefox.
setTimeout(function () {
URL.revokeObjectURL(url);
}, 100);
}
return (
<div>
<button onClick={startFunction()} >Record</button>
<button onClick={download()}> Download!</button>
</div>
);
}
}
export default Def;
And then run What happens is that I do get a message from Chrome that asks for permission to use the webcam but nothing is visible on the screen (not even the buttons) and it is completely blank. I feel like this issue might be due to some bindings which react needs but I am not sure :(
The error log now says:
bundle.js:33208 Uncaught TypeError: Cannot read property 'stop' of undefined
at download (bundle.js:33208)
at Def.render (bundle.js:33249)
at bundle.js:26631
at measureLifeCyclePerf (bundle.js:25910)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (bundle.js:26630)
at ReactCompositeComponentWrapper._renderValidatedComponent (bundle.js:26657)
at ReactCompositeComponentWrapper.performInitialMount (bundle.js:26197)
at ReactCompositeComponentWrapper.mountComponent (bundle.js:26093)
at Object.mountComponent (bundle.js:18474)
at ReactCompositeComponentWrapper.performInitialMount (bundle.js:26206)
this isn't a React issue - getUserMedia isn't supported across the board.
http://caniuse.com/#feat=stream
edit: my mistake - your error message actually tells you all you need to know: Expected onClick listener to be a function, instead got type string - you're literally passing in a string as the onClick handler, i.e onClick="startFunction()" - you want it to be onClick={yourFunction}

Deleting a file in FileSystem API after read is finished?

So I'm stuck trying to figure this out.
fileEntry.file(function(file){
var reader = new FileReader();
reader.onloadend = function (e) {
var anchor = document.createElement("a");
anchor.setAttribute('href', "data:text/tsv;charset=UTF-8," + encodeURIComponent(this.result));
anchor.setAttribute("download", "log.tsv");
anchor.innerHTML = "Download Log Now";
document.body.appendChild(anchor);
alert("Download by clicking the damn link at the bottom.");
//delete the file?
}
reader.readAsText(file);
});
So my question is how do you delete the file after it's been read? I've tried doing fileEntry.remove(function(){console.log("File Removed.")}); where the comment is but that doesn't work.
Any ideas?
You can have a look on promise-based bro-fs where this is more clean:
fs.init()
.then(() => fs.readFile('file.txt'))
.then(content => console.log(content))
.then(() => fs.unlink('file.txt'))

Categories