実験的な新しい React 機能Suspense for data fetching を使用しようとしています。
useApi
これは、(サスペンスを正しく理解している場合)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
意図したとおりに機能しますが、明らかにサスペンスは機能しません。
私がそれを機能させる別の方法は、次のように、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
サスペンスでの作業方法について、何かが欠けていますか?