Basic Reactivity

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 将返回最后返回的值,且不会触发 Suspensetransitions;如果还没有值返回,data.latest 的行为与 data() 相同。 当你想在新数据加载时显示过期数据时,这会很有用。

loadingerrorlatest 是响应式获取器,可以被追踪。


获取函数

fetcher 是你提供给 createResource 的异步函数,用于实际获取数据。 它接收两个参数:源信号的值(如果提供了的话)和一个包含两个属性的信息对象:valuerefetchingvalue 属性告诉你之前获取的值。 如果获取函数是通过 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
// 直接设置值而不创建 promise
mutate(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

  1. 我们添加了一个新的状态字段,它提供了比 loadingerror 更详细的资源状态视图。 你现在可以检查资源是否为 unresolvedpendingreadyrefreshingerror
状态值已解析加载中有错误
unresolved
pending
ready
refreshing
error
  1. 当服务器渲染资源时,特别是在将 Solid 嵌入到其他在渲染之前获取的系统中时,你可能希望使用这个预取的值来初始化资源,而不是再次获取并让资源在自己的状态中序列化它。 你可以使用新的 ssrLoadFrom 选项来实现这一点。 不使用默认的 server 值,你可以传入 initial,资源将在 SSR 和水合过程中使用 initialValue,就像它是第一次获取的结果一样。
const [data, { mutate, refetch }] = createResource(() => params.id, fetchUser, {
initialValue: preloadedData,
ssrLoadFrom: "initial",
})
  1. 通过使用 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 函数接受一个可选的第三个参数,即选项对象。选项包括:

名称类型默认值描述
namestringundefined资源的名称。用于调试目的。
deferStreambooleanfalse如果为 true,Solid 将在刷新流之前等待资源解析完成。
initialValueanyundefined资源的初始值。
onHydratedfunctionundefined资源水合时调用的回调函数。
ssrLoadFrom"server" | "initial""server"SSR 的初始值来源。如果设置为 "initial",资源将使用 initialValue 选项而不是获取函数返回的值。
storagefunctioncreateSignal返回信号的函数。可用于为资源创建自定义存储。这仍处于实验阶段。

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>
报告此页面问题