React Hook useEffect中如何在加载所有外部库后执行函数?

3
我希望在确保所有库加载完成后执行main()函数。
useEffect(() => { 
    for (const id in urls) {
      let tag = document.createElement('script');
      tag.async = false;
      tag.src = urls[id];
      let body = document.getElementsByTagName('body')[0];
      body.appendChild(tag);
    }
    main()
},[]); 

1
编写一个像这样加载脚本的组件似乎总体上并不是一个好主意。我建议在调用 ReactDOM.render() 之前加载那些脚本。 - Patrick Roberts
这个回答解决了你的问题吗?在脚本加载后调用JavaScript函数 - Agney
在确保加载所有库之后,请展示如何加载这些库。只有很少的细节,很难回答你的问题。 - Vencovsky
我有一个URL列表,其中包含const urls = ["https:...js", "http...js"]; - Masaki Minamide
1个回答

1
创建一个名为loadScript()的函数,它返回一个promise。该promise通过load事件处理程序进行解决。
const loadScript = url => new Promise(resolve => {
  const tag = document.createElement('script');
  tag.async = false;
  tag.src = url;
  const body = document.body;
  body.appendChild(tag);
  tag.addEventListener('load', resolve, {
    once: true
  });
});

现在您可以通过加载脚本将URL映射到Promise,并使用Promise.all()等待整个批次的加载。
useEffect(() => {
  Promise.all(Object.values(urls).map(loadScript))
    .then(main);
}, [urls]);

你可以创建一个自定义的useScripts hook来封装此功能:

const { useEffect, useState } = React;

const loadScript = (url, target) => new Promise(resolve => {
  const tag = document.createElement('script');
  tag.async = false;
  tag.src = url;
  target.appendChild(tag);
  tag.addEventListener('load', resolve, {
    once: true
  });
});

const useScripts = (urls, cb = () => {}, deps) => {
  useEffect(() => {
    const body = document.body;
  
    Promise.all(urls.map(url => loadScript(url, body)))
      .then(cb);
  }, deps);
}

const Demo = ({ urls }) => {
  const [loading, setLoading] = useState(true);
  
  useScripts(Object.values(urls), () => setLoading(false), [urls, setLoading]);
  
  return loading ? 'Loading' : 'done';
};

const urls = { lodash: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js', moment: 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js' };

ReactDOM.render(
  <Demo urls={urls} />,
  root
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接