如何从Redux迁移到React-Query?求基于现有代码的高亮实现示例
用React-Query Mutation实现评论高亮功能
核心思路
原来的Redux通过action和reducer更新客户端状态,改用React-Query时,我们可以利用Mutation结合缓存更新实现相同效果——因为高亮是客户端临时状态,无需同步到服务器,所以Mutation无需发送API请求,仅负责修改React-Query缓存中的评论数据。
实现步骤
1. 确保已用useQuery获取评论列表
假设你已经通过useQuery获取了评论数据,缓存key为['comments']:
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; // fetchComments为获取评论的API请求函数 const { data: comments } = useQuery(['comments'], fetchComments);
2. 创建更新高亮状态的Mutation
使用useMutation定义状态更新逻辑,在onSuccess回调中直接修改React-Query的缓存:
const queryClient = useQueryClient(); const updateHighlight = useMutation( // Mutation函数:仅传递参数,无需API请求 ({ parentId, isHighlighted }) => ({ parentId, isHighlighted }), { onSuccess: ({ parentId, isHighlighted }) => { // 更新缓存中的评论数据 queryClient.setQueryData(['comments'], (oldComments) => { if (!oldComments) return oldComments; return oldComments.map(comment => comment.id === parentId ? { ...comment, is_highlighted: isHighlighted } : comment ); }); } } );
3. 替换原鼠标事件逻辑
把原来的Redux dispatch调用替换为Mutation的mutate方法:
// 评论项组件中的鼠标事件 <div onMouseEnter={() => updateHighlight.mutate({ parentId: comment.parent, isHighlighted: true })} onMouseLeave={() => updateHighlight.mutate({ parentId: comment.parent, isHighlighted: false })} > {/* 评论内容 */} </div>
复用优化:封装自定义Hook
如果多个组件需要用到高亮功能,可以把Mutation逻辑封装成自定义Hook:
import { useMutation, useQueryClient } from '@tanstack/react-query'; export const useCommentHighlight = () => { const queryClient = useQueryClient(); return useMutation( ({ parentId, isHighlighted }) => ({ parentId, isHighlighted }), { onSuccess: ({ parentId, isHighlighted }) => { queryClient.setQueryData(['comments'], (oldComments) => { if (!oldComments) return []; return oldComments.map(comment => comment.id === parentId ? { ...comment, is_highlighted: isHighlighted } : comment ); }); } } ); };
在组件中直接导入使用:
import { useCommentHighlight } from './hooks'; const CommentItem = ({ comment }) => { const updateHighlight = useCommentHighlight(); return ( <div onMouseEnter={() => updateHighlight.mutate({ parentId: comment.parent, isHighlighted: true })} onMouseLeave={() => updateHighlight.mutate({ parentId: comment.parent, isHighlighted: false })} className={comment.is_highlighted ? 'highlighted' : ''} > {comment.content} </div> ); };
内容的提问来源于stack exchange,提问作者Butonix
相关产品推荐
相关产品推荐

