createResource
编辑此页面createResource
接收一个异步获取函数并返回一个信号,该信号在获取完成时会更新为结果数据。
有两种使用 createResource
的方式:你可以将获取函数作为唯一参数传入,或者也可以额外传入一个源信号作为第一个参数。
源信号在发生变化时会重新触发获取函数,其值将被传递给获取函数。
const [data, { mutate, refetch }] = createResource(fetchData)
const [data, { mutate, refetch }] = createResource(source, fetchData)
在这些代码片段中,获取函数是 fetchData
,在 fetchData
完成解析之前 data()
是未定义的。
在第一种情况下,fetchData
会立即被调用。
在第二种情况下,只有当 source
的值不为 false、null 或 undefined 时,fetchData
才会被调用。
当 source
的值发生变化时,它会再次被调用,且该值总是会作为第一个参数传递给 fetchData
。
你可以调用 mutate
直接更新 data
信号(它的工作方式和其他信号设置器一样)。
你也可以直接调用 refetch 重新运行获取函数,并可以传入一个可选参数为获取函数提供额外信息,例如 refetch(info)
。
data
的工作方式与普通的信号获取器相同:使用 data()
来读取 fetchData
最后返回的值。
但它还具有额外的响应式属性:data.loading
告诉你获取函数是否已被调用但尚未返回,data.error
告诉你请求是否出错;如果出错,它会包含获取函数抛出的错误。
(注意:如果你预期会出现错误,可能需要将 createResource
包装在 ErrorBoundary 中。)
从 v1.4.0 开始,data.latest
将返回最后返回的值,且不会触发 Suspense 和 transitions;如果还没有值返回,data.latest
的行为与 data()
相同。
当你想在新数据加载时显示过期数据时,这会很有用。
loading
、error
和 latest
是响应式获取器,可以被追踪。
获取函数
fetcher
是你提供给 createResource
的异步函数,用于实际获取数据。
它接收两个参数:源信号的值(如果提供了的话)和一个包含两个属性的信息对象:value
和 refetching
。
value
属性告诉你之前获取的值。
如果获取函数是通过 refetch 函数触发的,则 refetching
属性为 true,否则为 false。
如果使用参数调用了 refetch
函数(refetch(info)
),refetching 会被设置为该参数。
async function fetchData(source, { value, refetching }) { // 获取数据并返回一个值。 //`source` 告诉你源信号的当前值; //`value` 告诉你获取函数的最后返回值; //`refetching` 在通过调用 `refetch()` 触发获取函数时为 true, // 或等于传入的可选数据:`refetch(info)`}
const [data, { mutate, refetch }] = createResource(getQuery, fetchData)
// 读取值data()
// 检查是否正在加载data.loading
// 检查是否出错data.error
// 直接设置值而不创建 promisemutate(optimisticValue)
// 显式重新获取上一个请求refetch()
1.4.0 版本及更高版本
v1.4.0
如果你使用 renderToStream
,你可以使用 deferStream
选项告诉 Solid 在刷新流之前等待资源:
// 获取用户并尽快流式传输内容const [user] = createResource(() => params.id, fetchUser)
// 获取用户但只在此资源加载后才流式传输内容const [user] = createResource(() => params.id, fetchUser, { deferStream: true,})
v1.5.0
- 我们添加了一个新的状态字段,它提供了比
loading
和error
更详细的资源状态视图。 你现在可以检查资源是否为unresolved
、pending
、ready
、refreshing
或error
。
状态 | 值已解析 | 加载中 | 有错误 |
---|---|---|---|
unresolved | 否 | 否 | 否 |
pending | 否 | 是 | 否 |
ready | 是 | 否 | 否 |
refreshing | 是 | 是 | 否 |
error | 否 | 否 | 是 |
- 当服务器渲染资源时,特别是在将 Solid 嵌入到其他在渲染之前获取的系统中时,你可能希望使用这个预取的值来初始化资源,而不是再次获取并让资源在自己的状态中序列化它。
你可以使用新的
ssrLoadFrom
选项来实现这一点。 不使用默认的server
值,你可以传入initial
,资源将在 SSR 和水合过程中使用initialValue
,就像它是第一次获取的结果一样。
const [data, { mutate, refetch }] = createResource(() => params.id, fetchUser, { initialValue: preloadedData, ssrLoadFrom: "initial",})
- 通过使用 storage 选项,资源可以使用与信号相同签名的自定义定义存储进行设置。 例如,使用自定义协调存储可以这样做:
function createDeepSignal<T>(value: T): Signal<T> { const [store, setStore] = createStore({ value, }) return [ () => store.value, (v: T) => { const unwrapped = unwrap(store.value) typeof v === "function" && (v = v(unwrapped)) setStore("value", reconcile(v)) return store.value }, ] as Signal<T>}
const [resource] = createResource(fetcher, { storage: createDeepSignal,})
此选项仍处于实验阶段,将来可能会发生变化。
选项
createResource
函数接受一个可选的第三个参数,即选项对象。选项包括:
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
name | string | undefined | 资源的名称。用于调试目的。 |
deferStream | boolean | false | 如果为 true,Solid 将在刷新流之前等待资源解析完成。 |
initialValue | any | undefined | 资源的初始值。 |
onHydrated | function | undefined | 资源水合时调用的回调函数。 |
ssrLoadFrom | "server" | "initial" | "server" | SSR 的初始值来源。如果设置为 "initial" ,资源将使用 initialValue 选项而不是获取函数返回的值。 |
storage | function | createSignal | 返回信号的函数。可用于为资源创建自定义存储。这仍处于实验阶段。 |
TypeScript 用户注意事项
createResource
的函数和类型定义如下:
import { createResource } from "solid-js"import type { ResourceReturn, ResourceOptions } from "solid-js"
type ResourceReturn<T> = [ { (): T | undefined state: "unresolved" | "pending" | "ready" | "refreshing" | "errored" loading: boolean error: any latest: T | undefined }, { mutate: (v: T | undefined) => T | undefined refetch: (info: unknown) => Promise<T> | T }]
type ResourceOptions<T, S = unknown> = { initialValue?: T name?: string deferStream?: boolean ssrLoadFrom?: "initial" | "server" storage?: ( init: T | undefined ) => [Accessor<T | undefined>, Setter<T | undefined>] onHydrated?: (k: S | undefined, info: { value: T | undefined }) => void}
function createResource<T, U = true>( fetcher: ( k: U, info: { value: T | undefined; refetching: boolean | unknown } ) => T | Promise<T>, options?: ResourceOptions<T, U>): ResourceReturn<T>
function createResource<T, U>( source: U | false | null | (() => U | false | null), fetcher: ( k: U, info: { value: T | undefined; refetching: boolean | unknown } ) => T | Promise<T>, options?: ResourceOptions<T, U>): ResourceReturn<T>