主题
React 异步组件
1. 什么是异步组件
传统模式:渲染组件-> 请求数据 -> 再渲染组件。 异步模式:请求数据-> 渲染组件。
2. Suspense 的原理
通过包装一个子组件为一个异步模式(通过下面的 createFetcher 函数, 或者 React.lazy 函数), 然后马上抛出异常, 监听 Suspense 组件里的生命周期函数 componentDidCatch, 它会在监听异常的情况,然后来渲染 组件, 最后等异步模式回来的时候, 再渲染 组件;
js
// Suspense 实现
class Suspense extends React.Component {
state = { isRender: true };
componentDidCatch(e) {
/* 异步请求中,渲染 fallback */
this.setState({ isRender: false });
const { p } = e;
Promise.resolve(p).then(() => {
/* 数据请求后,渲染真实组件 */
this.setState({ isRender: true });
});
}
render() {
const { isRender } = this.state;
const { children, fallback } = this.props;
return isRender ? children : fallback;
}
}
createFetcher 立马抛出错误, 等拿到结果之后设置 status 为 resolved
js
// createFetcher
function createFetcher(fn) {
const fetcher = {
status: "pending",
result: null,
p: null
};
return () => {
fetcher.p = fn();
fetcher.p.then((res) => {
fetcher.status = "resolved";
fetcher.result = res;
});
if (fetcher.status === "pending") throw fetcher;
if (fetcher.status === "resolved") return fetcher.result;
};
}
LazyCom 的写的 3 种方式:
js
const LazyCom = createFetcher(async () => {
await new Promise((resolve) => setTimeout(resolve, 2000));
return <div>hello ,let us learn React</div>;
});
js
import HelloWorld from "./HelloWorld";
const LazyCom = createFetcher(
() =>
new Promise((resolve) => {
setTimeout(() => {
resolve(<HelloWorld />);
}, 2000);
})
);
js
const LazyCom = createFetcher(() =>
import("./HelloWorld").then((res) => {
return <res.default />;
})
);
组件进行包装
js
export default function Test() {
return (
<Suspense fallback={<div>loading...</div>}>
<LazyCom />
</Suspense>
);
}
正常使用 Suspense
js
const LazyCom = React.lazy(() => import("./HelloWorld"));
export default function Test() {
return (
<React.Suspense fallback={<div>loading...</div>}>
<LazyCom />
</React.Suspense>
);
}