数据变更
将我们的创建、更新和删除 endpoint 与 Controller.fetch() 配合使用,会以响应式的方式原子地(同时)更新_所有_相关组件。
useController() 让组件可以使用这个全局的、功能增强版的 setState()。
TodoResource
TodoItem
CreateTodo
TodoList
import { useController } from '@data-client/react'; import { TodoResource, type Todo } from './TodoResource'; export default function TodoItem({ todo }: { todo: Todo }) { const ctrl = useController(); const handleChange = e => ctrl.fetch( TodoResource.partialUpdate, { id: todo.id }, { completed: e.currentTarget.checked }, ); const handleDelete = () => ctrl.fetch(TodoResource.delete, { id: todo.id, }); return ( <div className="listItem nogap"> <label> <input type="checkbox" checked={todo.completed} onChange={handleChange} /> {todo.completed ? <s>{todo.title}</s> : todo.title} </label> <CancelButton onClick={handleDelete} /> </div> ); }
结果
Store▶
Data Client 不会触发级联失效,也不需要手写更新函数,而是利用 fetch 响应以响应式的方式更新相关组件。
基于先前状态的乐观变更
Post
PostResource
PostItem
TotalVotes
PostList
import { resource } from '@data-client/rest'; import { Post } from './Post'; export { Post }; export const PostResource = resource({ path: '/posts/:id', searchParams: {} as { userId?: string | number } | undefined, schema: Post, }).extend('vote', { path: '/posts/:id/vote', method: 'POST', body: undefined, schema: Post, getOptimisticResponse(snapshot, { id }) { const post = snapshot.get(Post, { id }); if (!post) throw snapshot.abort; return { id, votes: post.votes + 1, }; }, });
结果
Store▶
getOptimisticResponse 就像使用更新函数的 setState。Snapshot 提供对先前 store 值的类型安全访问,我们用它来返回_预期的_ fetch 响应。
Reactive Data Client 能在任何可能的网络故障或竞态条件下确保数据完整性,因此你无需担心网络故障、多次变更调用编辑同一份数据,或异步编程中的其他常见问题。
跟踪变更的加载状态
useLoading() 通过跟踪异步函数的加载状态和错误状态来增强它们。
PostResource
PostDetail
PostForm
PostCreate
Navigation
import { useLoading, useController } from '@data-client/react'; import { PostResource } from './PostResource'; import PostForm from './PostForm'; export default function PostCreate({ navigateToPost }) { const ctrl = useController(); const [handleSubmit, loading, error] = useLoading( async data => { const post = await ctrl.fetch(PostResource.getList.push, data); navigateToPost(post.id); }, [ctrl], ); return ( <PostForm onSubmit={handleSubmit} loading={loading} error={error} /> ); }
结果
Store▶