useResource$()
此方法允许您异步生成计算值(计算属性)。 它的第一个参数是一个异步函数,该函数将在 组件mounted 和 跟踪值变化 的时候被调用。
和所有use-
方法一样,它必须在 component()
的上下文中调用,
and all the hook rules apply.
const store = useStore({
bar: 'foo'
})
const resource = useResource$(async (ctx) => {
ctx.track(() => store.bar); // the resource will rerun when store.bar changes.
ctx.track(() => props.url); // track() can be called multiple times, to track multiple values
ctx.cleanup(() => {
// In case the resource need to be cleaned up, this function will be called.
// Allowing to clean resources like timers, subscriptions, fetch requests, etc.
});
// cleanup() can also be called multiple times.
ctx.cleanup(() => console.log('cleanup'));
// Resources can contain async computations
const value = await expensiveCompute(store.bar, props.url);
return value;
});
正如我们在上面的示例中看到的,useResouce()
返回一个 ResourceReturn<T>
对象,
它的工作方式类似于一个美化的、完全反应式的promise,包含数据和资源状态。
resource.state
可能是下面几个字符串中的一个:
'pending'
- 数据还不可用'resolved'
- 数据已可用'rejected'
- 由于错误或超时原因,数据不可用
传给useResource$()
的回调函数在useMount$()
和 useWatch$()
的回调函数 完成执行后立马调用。
更多细节请参考Lifecycle 部分。
<Resource>
<Resource>
是一个组件,它在数据resolved时渲染子元素,并在数据pending或rejected时渲染兜底UI。
<Resource
value={weatherResource}
onPending={() => <div>Loading...</div>}
onRejected={() => <div>Failed to load weather</div>}
onResolved={(weather) => {
return <div>Temperature: {weather.temp}</div>;
}}
/>
请注意,使用 useResource()
时不是必须也要使用<Resource>
的。
<Resource>
只是渲染数据的一种便捷方式。
useResource$()
和 <Resource>
的例子
使用 示例展示了 每次在输入的城市名称改变时,使用useResource
执行fetch调用以请求天气数据。
export const Cmp = component$(() => {
const store = useStore({
city: '',
});
const weatherResource = useResource$<any>(async ({ track, cleanup }) => {
const cityName = track(() => store.city);
const abortController = new AbortController();
cleanup(() => abortController.abort('cleanup'));
const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
signal: abortController.signal,
});
const data = res.json();
return data;
});
return (
<div>
<input name="city" onInput$={(ev: any) => (store.city = ev.target.value)} />
<Resource
value={weatherResource}
onPending={() => <div>Loading...</div>}
onResolved={(weather) => {
return <div>Temperature: {weather.temp}</div>;
}}
/>
</div>
);
});
<Resource>
的例子
不使用 export const Cmp = component$(() => {
const store = useStore({
city: '',
});
const weatherResource = useResource$<any>(async ({ track, cleanup }) => {
const cityName = track(() => store.city);
const abortController = new AbortController();
cleanup(() => abortController.abort('cleanup'));
const res = await fetch(`http://weatherdata.com?city=${cityName}`, {
signal: abortController.signal,
});
const data = res.json();
return data;
});
return (
<div>
<input name="city" onInput$={(ev: any) => (store.city = ev.target.value)} />
{weatherResource.state === 'pending' && (
<div>Loading...</div>
)}
{weatherResource.state === 'resolved' && (
<div>Temperature: {weatherResource.resolved.temp}</div>
)}
</div>
);
});
注意 我们强烈建议尽可能使用
<Resource>
,因为该组件将更有效地避免重新渲染,并且还针对 SSR 进行了优化。