Загрузка скрипта в react

Я хочу загрузить скрипт из 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 " недоступен, и я получаю такую ошибку:

TypeError: не удается прочитать свойство "render" undefined

как я могу уверить, что componentDidMount() вызывается после успешной загрузки скрипта?

1 ответов


Я думаю, что это не хорошая идея загрузить скрипт в componentWillMount () или componentDidMount (), согласно спецификации и жизненный цикл компонентов React.

ниже код может помочь вам.

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>
    );
  }
}