我想从CDN加载脚本,然后在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> ); }
该脚本有时需要花费一些时间(通常是第一次)加载,并且何时componentDidMount()调用“ foo”不可用,并且出现如下错误:
componentDidMount()
TypeError:无法读取未定义的属性“ render”
如何确保componentDidMount()脚本成功加载后调用?
根据React Component Specs和Lifecycle的说法,我认为在componentWillMount()或componentDidMount()中加载脚本不是一个好主意。
下面的代码可能会对您有所帮助。
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> ); } }