Daxus是一个针对React应用程序量身定制的杰出服务器状态管理库。使用Daxus,开发人员可以完全控制他们的数据,使他们能够以优越的用户体验来制作网站。
通过Daxus建立更好的用户体验
让我们考虑开发论坛网站的情况。我们的网站包括各种帖子列表,例如“流行”,“最新”,“推荐”等。用户可以通过喜欢这些帖子来与帖子进行交互,并且帖子将显示喜欢的总数。
最初,我们可能会选择React查询来管理服务器数据。这是我们如何使用React查询的一个示例:
import { useQuery, useInfiniteQuery } from '@tanstack/react-query';
export function usePost(id: number) {
return useQuery({
queryKey: ['post', 'detail', id],
queryFn: () => axios.get(`/api/post/${id}`)
});
}
export function usePostList({ forumId, filter }: { forumId: string; filter: 'popular' | 'latest' | 'recommended' }) {
return useInfiniteQuery({
queryKey: ['post', 'list', forumId, filter],
queryFn: ({ pageParam = 0 }) => axios.get(`/api/post?page=${pageParam}&forumId=${forumId}&filter=${filter}`),
getNextPageParam: (lastPage, pages) => lastPage.nextCursor
});
}
React Query提供了useQuery
和useInfiniteQuery
挂钩以简化数据处理。仅使用queryKey
和queryFn
,React查询有效地管理了我们的数据。
现在,让我们讨论喜欢帖子的用户的逻辑:
import { useMutation, useQueryClient } from '@tanstack/react-query';
export function useLikePost(id: number) {
const client = useQueryClient();
return useMutation({
mutationFn: () => {
return likePostApi({ id });
},
onSuccess: () => {
client.invalidateQueries({ queryKey: ['post'] });
}
});
}
当用户喜欢帖子时,我们会使所有帖子数据无效,触发用户当前正在查看的帖子。此外,当用户返回帖子列表时,它也会进行倒置,显示更新的count。
但是,用户喜欢帖子和显示更新的count的帖子之间存在明显的延迟。要在“帖子”视图中解决此问题,我们可以实现乐观的更新:
export function useLikePost(id: number) {
const client = useQueryClient();
return useMutation({
mutationFn: () => {
return likePostApi({ id });
},
onMutate: async () => {
await client.cancelQueries({ queryKey: ['post', 'detail', id] });
client.setQueryData(['post', 'detail', id], (old) => ({ ...old, likeCount: old.likeCount + 1 }));
},
onError: () => {
client.setQueryData(['post', 'detail', id], (old) => ({ ...old, likeCount: old.likeCount - 1 }));
},
onSettled: () => {
client.invalidateQueries({ queryKey: ['post'] });
}
});
}
现在,用户可以在喜欢帖子后立即看到结果。但是,当他们返回帖子列表时,他们仍然会看到旧的帖子数据。他们必须等待一些延迟才能查看最新结果。考虑我们网站上的多个列表,在每个列表中找到帖子,然后执行乐观更新并不有效。
达克斯救援!
输入Daxus!使用Daxus,我们可以为我们的帖子数据创建自定义数据结构,以确保每个邮政实体都引用相同的数据。此功能使我们可以消除延迟问题而不会出现任何麻烦。让我们看看如何使用daxus管理帖子数据:
import { createDatabase, createPaginationAdapter, useAccessor } from 'daxus';
export const database = createDatabase();
export const postAdapter = createPaginationAdapter<Post>();
export const postModel = database.createModel({name: 'post', initialState: postAdapter.initialState});
export const getPost = postModel.defineAccessor({
name: 'getPost',
async fetchData(id: number) {
return axios.get(`/api/post/${id}`);
},
syncState( draft, { data } ) {
postAdapter.upsertOne(draft, data);
}
})
export const listPost = postModel.defineInfiniteAccessor({
name: 'listPost',
async fetchData({forumId, filter}: {forumId: string, filter: 'popular' | 'latest' | 'recommended'}, {previousData}) {
const page = previousData?.nextCursor ?? 0;
return axios.get(`/api/post?page=${page}&forumId=${forumId}&filter=${filter}`);
},
syncState( draft, { data, arg: { forumId, filter} }) {
const key = `${forumId}&${filter}`;
postAdapter.appendPagination(draft, key, data);
}
})
export function usePost(id: number) {
return useAccessor(getPost(id), state => postAdapter.tryReadOne(state, id));
}
export function usePostList({forumId, filter}: {forumId: string, filter: 'popular' | 'latest' | 'recommended'}) {
return useAccessor(listPost({forumId, filter}), state => {
const key = `${forumId}&${filter}`;
return postAdapter.tryReadPagination(state, key)?.items
});
}
export async function likePost(id: number) {
postModel.mutate(draft => {
postAdapter.readOne(draft, id).likeCount += 1;
})
try {
await likePostApi({id});
} catch {
postModel.mutate(draft => {
postAdapter.readOne(draft, id).likeCount -= 1;
})
} finally {
postModel.invalidate();
}
}
在达克斯(Daxus)中,我们提供了有关如何在服务器中获取数据后如何更新状态的必要说明。 createPaginationAdapter
函数返回具有用于访问分页数据的操作的对象。如果我们需要更自定义的数据结构,我们也可以构建适配器。
由于分页数据结构中的每个实体都会引用相同的数据,因此当用户喜欢帖子并返回到任何列表时,他们会立即查看他们是否喜欢该帖子。没有延误,没有大惊小怪 - 只是无缝的用户体验!
有关更多详细信息和代码示例,请访问Daxus GitHub repository。
daxus正在不断发展,您的宝贵反馈对于使其变得更好至关重要!尝试Daxus尝试与我们分享您的想法!让我们一起创建出色的反应应用程序!