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



我想在确保加载所有库后执行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()
},[]); 

创建一个返回 promise 的loadScript()函数。承诺通过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.all()等待整个批处理的加载:

useEffect(() => {
Promise.all(Object.values(urls).map(loadScript))
.then(main);
}, [urls]);

您可以创建自定义useScripts挂钩来封装此功能:

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>

相关内容

  • 没有找到相关文章

最新更新