如何显示加载器时,有阻塞代码在onClick处理程序?



我有一个简单的react组件。该组件有一个处理程序,在单击按钮时运行。处理程序中有一些阻塞代码。我的任务是:当我点击按钮加载器出现。之后,阻塞代码执行一些繁重的操作,之后,加载器消失:

import { useState } from "react";
import "./styles.css";
export default function App() {
const [wait, setWait] = useState(true);
const onClickHandler = () => {
setWait(true);
// Blocking code
setWait(false);
};
return (
<div className="App">
<button onClick={onClickHandler}>Click</button>
{wait && <div>Loading...</div>}
</div>
);
}

这段代码是人为的,我知道最好不要这样做——阻塞线程。我知道分批处理在这里是有效的。但是,我仍然想知道如何在这种情况下显示加载器。一般来说,这种情况在生产中是可能的,还是一种不好的做法?

有两种方法

  1. 稍后执行阻塞代码,让加载指示符先显示。

new PromisesetTimeout都可以。

export default function App() {
const [wait, setWait] = useState(true);
const onClickHandler = () => {
setWait(true);
new Promise((resolve) => {
// Blocking code
setWait(false);
resolve()
});
};
return (
<div className="App">
<button onClick={onClickHandler}>Click</button>
{wait && <div>Loading...</div>}
</div>
);
}
  1. 把你的block代码扔给Web Worker。

您可以使用自定义钩子,如useWorker来方便地实现此

useWorker: https://github.com/alewin/useWorker

阻塞代码意味着页面中的任何其他操作都必须等待第一个操作完成。如果你不关心这种情况的发生(也许这个加载程序覆盖了整个屏幕,或者你不希望用户在操作完成之前做任何其他事情),那么这是可以的。

现在,也许您想在用户与页面交互时执行此操作,在这种情况下,您应该通过使用then/catch/finally语法来利用Promise的异步行为。您还需要useRef,以便您可以在回调中访问组件的当前状态。

import { useState, useRef } from "react";
import "./styles.css";
export default function App() {
// your big operation should return a Promise
const bigOperation = () => {
return new Promise((resolve, reject) => {
resolve("Heeeey");
})
}
// added "_" to the set function so it won't be confused
// with our function to update the reference
const [wait, _setWait] = useState(true);
// create reference for the wait state
const waitRef = useRef(wait);
// function to update reference and state (mimics real one _setWait)
const setWait = (newValue) => {
waitRef.current = newValue;
_setWait(newValue);
}
const onClickHandler = () => {
setWait(true);
// this executes asyncronously
bigOperation().then(() => {
setWait(false);
});
};
return (
<div className="App">
<button onClick={onClickHandler}>Click</button>
{wait && <div>Loading...</div>}
</div>
);
}

我将把条件移到主返回语句之外。

if (wait) return <div>Loading...</div>;
return (
<div className="App">
<button onClick={onClickHandler}>Click</button>
</div>
);

相关内容

  • 没有找到相关文章

最新更新