Suppose I had the following two files:
example.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8" />
<title>Example</title>
<script type="text/javascript" src="BodyPrinter.js"></script>
</head>
<body id="body" onload="init()">
<button onclick="bodyPrinter.printBody()">Print body</button>
<script>
function init() {
bodyPrinter = new BodyPrinter();
}
</script>
</body>
</html>
BodyPrinter.js
function BodyPrinter() {
this.body = document.getElementById('body');
};
BodyPrinter.prototype.printBody = function () {
console.log(this.body);
}
This prints the of the HTML when the button is clicked. This works because the HTML is first loaded, with all of its elements, and then the init() creates the BodyPrinter that will access the HTML element and print it.
Right now I'm converting to React, and attempting to change as little as possible (aside from adding an export export default BodyPrinter;
in BodyPrinter.js);
convert.jsx
import * as React from 'react';
import BodyPrinter from './BodyPrinter';
export default class Entry extends React.Component {
constructor(props) {
super(props);
this.bodyPrinter = new BodyPrinter();
}
render() {
return (
<div>
<title>Example</title>
<button onClick={() => this.bodyPrinter.printBody()}>Print body</button>
</div>
)
}
}
For my purposes, I need to access BodyPrinter in the render() method, therefore I need to create it in the constructor. The issue is that the constructor is called before the HTML is created, so the BodyPrinter will just print null.
How can I resolve this/get the HTML to load first without modifying BodyPrinter.js and still being able to access it in the render()?
Solution:
I've figured a solution. Just place the classes you want to instantiate in componentDidMount() instead of the constructor. That way you can still access them in the render().