Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
62
rated 0 times [  68] [ 6]  / answers: 1 / hits: 37719  / 7 Years ago, fri, march 17, 2017, 12:00:00

I want to load the script from a CDN and then execute a function exposed by that script in React:



componentWillMount() {
console.log('componentWillMount is called');
const script = document.createElement('script');
script.src = 'https://foo.azurewebsites.net/foo.js';
document.body.appendChild(script);
}


componentDidMount() {
console.log('componentDidMount is called');
window.foo.render({
formId: '77fd8848-791a-4f13-9c82-d24f9290edd7',
}, '#container');
}


render() {
console.log('render is called');
return (
<div id=container></div>
);
}


The script sometimes takes time to load (generally first time) and when componentDidMount() is called foo is not available and I get an error like this:




TypeError: Cannot read property 'render' of undefined




How can I assure that componentDidMount() is called once the script is loaded successfully?


More From » reactjs

 Answers
30

I don't think it's a good idea to load scripts in componentWillMount() or componentDidMount(), according to React Component Specs and Lifecycle.



The code below may help you.



function new_script(src) {
return new Promise(function(resolve, reject){
var script = document.createElement('script');
script.src = src;
script.addEventListener('load', function () {
resolve();
});
script.addEventListener('error', function (e) {
reject(e);
});
document.body.appendChild(script);
})
};
// Promise Interface can ensure load the script only once.
var my_script = new_script('http://example.com/aaa.js');

class App extends React.Component {

constructor(props) {
super(props);
this.state = {
status: 'start'
};
}

do_load = () => {
var self = this;
my_script.then(function() {
self.setState({'status': 'done'});
}).catch(function() {
self.setState({'status': 'error'});
})
}

render() {
var self = this;
if (self.state.status === 'start') {
self.state.status = 'loading';
setTimeout(function () {
self.do_load()
}, 0);
}

return (
<div>{self.state.status} {self.state.status === 'done' && 'here you can use the script loaded'}</div>
);
}
}

[#58511] Wednesday, March 15, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
yasmeeng

Total Points: 516
Total Questions: 97
Total Answers: 101

Location: South Korea
Member since Fri, Sep 11, 2020
4 Years ago
;