我正在尝试使用实验性的新 React 功能Suspense 进行数据获取。
这是我的简单useApi
钩子(如果我正确理解 Suspense 的话)要么返回fetch
调用结果,要么抛出吊杆承诺。(稍微修改了记录的示例)
function useApi(path) {
const ref = React.useRef({ time: +new Date() });
if (!ref.current.suspender) {
ref.current.suspender = fetch(path).then(
data => ref.current.data = data,
error => ref.current.error = error,
);
}
if (ref.current.data) return ref.current.data;
if (ref.current.error) return ref.current.error;
throw ref.current.suspender;
}
我正在使用这个钩子,就像这样:
function Child({ path }) {
const data = useApi(path);
return "ok";
}
export default function App() {
return (
<Suspense fallback="Loading…">
<Child path="/some-path" />
</Suspense>
);
}
它永远不会解决。
我认为问题在于它useRef
并没有像预期的那样工作。
如果我用随机值初始化 ref,它不会保留该值,而是用另一个随机值重新初始化:
const ref = React.useRef({ time: +new Date() });
console.log(ref.current.time)
1602067347386
1602067348447
1602067349822
1602067350895
...
抛出suspender
会导致useRef
每次调用都重新初始化,这有点奇怪。
throw ref.current.suspender;
如果我删除该行useRef
按预期工作,但显然 Suspense 不起作用。
我可以使它工作的另一种方法是,如果我在 React 之外使用某种自定义缓存,例如:
const globalCache = {}
function useApi(path) {
const cached = globalCache[path] || (globalCache[path] = {});
if (!cached.suspender) {
cached.suspender = ...
}
if (cached.data) ...;
if (cached.error) ...;
throw cached.suspender;
}
这也使它工作,但我宁愿使用 React 本身在缓存组件特定数据方面提供的东西。
我是否遗漏了一些关于useRef
应该如何使用或不应该使用 Suspense 的内容?