前言
Solid.js,一个比 React 更 react 的框架。每一个使用 React 的同学,你可以不使用,但不应该不了解。
目前 Solid.js 发布了最新的官方文档,但却缺少对应的中文文档。为了帮助大家学习 Solid.js,为爱发电翻译文档。
我同时搭建了 Solid.js 最新的中文文档站点:solid.yayujs.com ,欢迎勘误。
虽说是翻译,但个人并不喜欢严格遵守原文,为了保证中文阅读流畅,会删减部分语句,对难懂的部分也会另做补充解释,希望能给大家带来一个好的中文学习体验。
欢迎围观我的“朋友圈”、加入“低调务实优秀中国好青年”前端社群,分享技术,带你成长。
获取数据
对于大多数现代 Web 应用程序来说,数据获取是一项常见任务。 Solid 有一个内置实用程序 createResource
,它是为了简化数据获取而创建的。
createResource
是什么?
createResource
是专门为管理异步数据获取而设计的定制 signal 。它包装了异步操作,提供了一种处理各种状态的方法,包括加载、成功和错误状态。
此函数是非阻塞的,这意味着 createResource
保证应用程序保持响应,即使在信息检索期间也是如此。因此,可以避免传统异步处理的常见缺陷,例如数据获取期间 UI 无响应。
使用 createResource
createResource
需要一个返回 Promise 作为其参数的函数。调用时,createResource
返回一个具有响应属性(如加载、错误、最新等)的 signal。这些属性可用于根据当前响应状态有条件地渲染 JSX。
创建的 fetcher
函数会调用以获取数据,然后将其作为参数传递给 createResource
。
从 createResource
返回的 signal 提供了可以帮助基于当前响应式状态进行条件渲染的属性:
state
: 操作的当前状态 (unresolved
,pending
,ready
,refreshing
, 或errored
)。loading
: 通过一个boolean
值表示当前操作正在进行中。error
: 如果操作因一些原因失败,此属性将包含有关此错误的信息。它可能是带有错误消息的字符串,也可能是带有更详细信息的对象。latest
: 操作返回的最新数据或结果。
当源 signal 发生变化时,会基于这次改变触发一个内部的 fetch 以检索新数据。
import { createSignal, createResource, Switch, Match, Show } from "solid-js";
const fetchUser = async (id) => {
const response = await fetch(`https://swapi.dev/api/people/${id}/`);
return response.json();
}
function App() {
const [userId, setUserId] = createSignal();
const [user] = createResource(userId, fetchUser);
return (
<div>
<input
type="number"
min="1"
placeholder="Enter Numeric Id"
onInput={(e) => setUserId(e.currentTarget.value)}
/>
<Show when={user.loading}>
<p>Loading...</p>
</Show>
<Switch>
<Match when={user.error}>
<span>Error: {user.error}</span>
</Match>
<Match when={user()}>
<div>{JSON.stringify(user())}</div>
</Match>
</Switch>
</div>
);
}
每当 signal 值 userId
发生变化时,就会触发内部 fech 方法 fetchUser
。 user
resource 的属性允许根据获取过程的不同状态进行条件渲染。
Switch/Match
提供了一种管理这些条件的方法。当获取成功并检索到用户数据时,user()
条件变为激活状态,并且渲染其内容。但是,如果获取时出现错误, user.error
将变为 true
,从而导致显示其相应的 Match
块。
除了 error
属性之外,loading
属性还提供了一种在数据获取期间向用户展示加载状态的方法。
调用多个异步事件
虽然您可以独立使用 createResource
,但 Solid 提供了另一种方法来同步多个异步事件的显示。
Suspense
是 Solid 中的一个组件,旨在充当边界。它允许您在等待所有异步事件 resolve 时显示 fallback 占位符,从而防止显示部分加载内容:
import { createSignal, createResource, Switch, Match, Suspense } from "solid-js";
const fetchUser = async (id) => {
const response = await fetch(`https://swapi.dev/api/people/${id}/`);
return response.json();
}
function App() {
const [userId, setUserId] = createSignal();
const [user] = createResource(userId, fetchUser);
return (
<div>
<input
type="number"
min="1"
placeholder="Enter Numeric Id"
onInput={(e) => setUserId(e.currentTarget.value)}
/>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Match when={user.error}>
<span>Error: {user.error.message}</span>
</Match>
<Match when={user()}>
<div>{JSON.stringify(user())}</div>
</Match>
</Switch>
</Suspense>
</div>
);
}
Suspense
能够识别其后代中的异步读取并采取相应的操作。此功能有助于删除任何可能在部分加载状态期间显示的中间组件。此外,您可以根据需要在 Suspense
中嵌套任意数量的组件,但当检测到加载状态时,只有最接近的祖先才会切换到 fallback
状态。
动态数据处理
对于 createResource
的第二个输出,有两种强大的方法旨在增强和简化数据管理的复杂性:
mutate
在即时反馈或响应性很重要的情况下,mutate
方法提供“乐观更新”。即使后台进程(例如服务器确认)仍在进行中,这些更新也会提供即时反馈。
此功能在任务列表等应用程序中特别有价值。例如,当用户输入新任务并单击 Add
按钮时,列表将立即刷新,而不管与服务器正在进行的数据通信如何。
import { For, createResource } from "solid-js"
function TodoList() {
const [tasks, { mutate }] = createResource(fetchTasksFromServer);
return (
<>
<ul>
<For each={tasks()}>
{(task) => (
<li>{task.name}</li>
)}
</For>
</ul>
<button
onClick={() => {
mutate((todos) => [...todos, "do new task"]); // add todo for user
// make a call to send to database
}}
>
Add Task
</button>
</>
);
}
refetch
当需要实时反馈时,可以使用 refetch
方法重新加载当前查询,而不管发生任何变化。当数据不断变化时,例如实时金融应用程序,此方法特别有用。
import { createResource, onCleanup } from "solid-js"
function StockPriceTicker() {
const [prices, { refetch }] = createResource(fetchStockPrices);
const timer = setInterval(() => {
refetch()
}, 1000);
onCleanup(() => clearInterval(timer))
}
Solid.js 中文文档
本篇已收录在掘金专栏 《Solid.js 中文文档》,该系列一共 25 篇。下一篇:Solid.js 最新官方文档翻译(21)—— 测试
此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、VuePress 博客搭建系列等 14 个系列文章, 全系列文章目录:github.com/mqyqingfeng…
通过文字建立交流本身就是一种缘分,欢迎围观我的“朋友圈”、加入“低调务实优秀中国好青年”前端社群,分享技术,带你成长。