In vanilla JS, my code would work fine. For this case, I'd like to componentize my Wall
class which's supposed to display the image in the browser that the user has uploaded. Again, this works normally in vanilla JS but not JSX.
I'm getting a potentially invalid reference access to a class field via this in a nested function
on the document.querySelector("#file-input").addEventListener("change", this.previewImages);
line which I think is causing the issue.
What am I doing wrong and how can I fix it?
import React, {Component} from 'react';
class Wall extends Component {
constructor(props) {
super(props);
this.previewImages = this.previewImages.bind(this);
}
previewImages() {
let preview = document.createElement("div");
if (this.files) {
[].forEach().call(this.files, readAndPreview());
}
function readAndPreview() {
if (!/\.(jpe?g|png|gif)$/i.test(file.name)) {
return alert(file.name + " is not an image");
}
let reader = new FileReader();
reader.addEventListener("load", () => {
let image = new Image();
image.height = 100;
image.title = file.name;
image.src = this.result;
let date = Date.now();
let d = new Date(parseInt(date, 10));
let ds = d.toString("MM/dd/yy HH:mm:ss");
console.log(ds);
let initialCountOfLikes = 0;
let zeroLikes = document.createElement("h1");
let zeroLikesTextNode = zeroLikes.createTextNode(initialCountOfLikes + " likes");
zeroLikes.appendChild(zeroLikesTextNode);
preview.appendChild(image); // makes image appear
preview.appendChild(zeroLikes); // makes like count appear
image.ondblclick = function() {
if (initialCountOfLikes === 0) {
console.log("Inside if block");
initialCountOfLikes++;
console.log("initialCountOfLikes++ => " + initialCountOfLikes);
} else if (initialCountOfLikes === 1) {
console.log("inside second else if block");
initialCountOfLikes--;
console.log("initialCountOfLikes-- => " + initialCountOfLikes);
}
zeroLikesTextNode.nodeValue = initialCountOfLikes + " likes";
};
});
reader.readAsDataURL(file);
document.querySelector("#file-input").addEventListener("change", this.previewImages);
}
}
render() {
return (
<div id="file-input-wrapper">
<input type="file" />
<label htmlFor="file-input" id={"LblBrowse"} />
</div>
);
}
}
export default Wall;
The warning is telling you that using this
in JavaScript frequently has confusing implications, specifically when used inside a function nested inside another function. this
stops referring to the class, and instead refers to the scope of your nested function.
In your case, this probably is a legitimate problem (I think) because you have your class, Wall
, which has a method previewImages()
and a property files
. Within that function, you have instantiated a new function, readAndPreview()
, inside which you specify this.previewImages
as a function callback to the addEventListener
function.
They're saying you're potentially using this.previewImages
incorrectly, because you're writing functions in traditional JavaScript syntax, function foo() { ... }
, where this
keeps being redefined in each child function call. In your case, I believe that this
is referring to the context of readAndPreview()
, and hence cannot access the method this.previewImages()
since this
doesn't refer to your parent class, Wall
.
People used to do things like, make a var that = this;
on the parent class, and you'd know that that
always meant the parent class.
But now, with ES6 lambda functions using the "fat arrow" syntax () => { }
you can access this
and know it's referring to the parent scope.
I believe you can refactor your class to change previewImages() {
into previewImages = () => {
and know that this
will refer to the class. You'll have to do the same with function readAndPreview() {
. Change it to const readAndPreview = () => {
. If you're setting it to a variable, though, I think you'll have to move it above the place you call it, though. e.g. above
if (this.files) {
[].forEach().call(this.files, readAndPreview());
}
I faced this error in Angular 8. I used the Arrow function instead of regular functions to solve.
In your case.
readAndPreview = () => { ... }
This might solve your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With