为什么选择 tsup?
2025年3月30日 18:03
前端构建工具技术选型:为什么选择 tsup? 目录 什么是 tsup? 核心优势 与其他工具对比 适用场景 快速配置示例 何时不推荐使用 tsup? 总结 1. 什么是 tsup? tsup 是一个零
在日常开发中,我们经常需要处理异步操作(如表单提交、数据更新等),这些操作通常涉及以下问题:
传统的写法需要我们手动处理这些问题,而 useMutation 提供了一个优雅的解决方案。
const CategoryForm = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const handleSubmit = async (values: CategoryFormData) => {
setLoading(true);
setError(null);
try {
const response = await request.post('/api/category', values);
message.success('添加成功');
// 刷新列表
tableRef.current?.reload();
} catch (err) {
setError(err as Error);
message.error('添加失败:' + (err as Error).message);
} finally {
setLoading(false);
}
};
return (
<Form onFinish={handleSubmit}>
<Form.Item>
<Button loading={loading} type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
{error && <div className="error-message">{error.message}</div>}
</Form>
);
};
const CategoryForm = () => {
const { mutate, isLoading, error } = useMutation(
(values: CategoryFormData) => request.post('/api/category', values),
{
onSuccess: () => {
message.success('添加成功');
tableRef.current?.reload();
},
onError: (error) => {
message.error('添加失败:' + error.message);
}
}
);
return (
<Form onFinish={mutate}>
<Form.Item>
<Button loading={isLoading} type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
{error && <div className="error-message">{error.message}</div>}
</Form>
);
};
代码更简洁
类型安全
状态管理自动化
const { data, loading, run } = useRequest(fetchData, {
manual: true,
onSuccess: (result) => {
console.log(result);
},
});
const { mutate, isLoading, data } = useMutation(updateData, {
onSuccess: (result) => {
console.log(result);
},
});
使用场景
功能特点
状态管理
useMutation 提供了完整的生命周期钩子,让你可以在请求的不同阶段执行自定义逻辑:
onMutate: 在发起请求前调用
onSuccess: 请求成功后调用
onError: 请求失败时调用
onSettled: 请求完成后调用(无论成功或失败)
所有生命周期钩子都支持返回 Promise,这带来几个重要优势:
流程控制: 允许在一个生命周期完成后再进入下一阶段
onMutate: async (variables) => {
// 等待缓存操作完成后再发送请求
await queryClient.cancelQueries(['todos']);
const previousTodos = queryClient.getQueryData(['todos']);
// 没有返回reject,说明可以行下
}
组合多个操作: 可以将多个相关的异步操作组合在一起
onSettled: async () => {
// 确保这些操作按顺序完成
await queryClient.invalidateQueries(['todos']);
await resetForm();
await closeModal();
}
这种设计使 useMutation 在处理复杂的数据修改流程时更加灵活和强大,特别是当操作涉及多个步骤或依赖其他异步操作时。
const SubmitForm = () => {
const { mutate, isLoading } = useMutation(submitForm, {
onSuccess: (data) => {
message.success('提交成功');
// 可以直接使用返回的数据
console.log(data);
},
onError: (error) => {
// 错误处理更集中
handleError(error);
}
});
return <Form onFinish={mutate}>...</Form>;
};
const BatchOperation = () => {
const { mutate, isLoading } = useMutation(batchDelete, {
// 操作前的准备工作
onMutate: (variables) => {
// 做一些验证操作
},
// 乐观更新
onSuccess: (data, variables) => {
message.success('操作成功');
},
// 失败
onError: (error, variables) => {
//错误处理
}
});
return (
<Button
loading={isLoading}
onClick={() => mutate({ ids: selectedRows })}
>
批量删除
</Button>
);
};
const StatusToggle = () => {
const { mutate } = useMutation(toggleStatus, {
onMutate: (newStatus) => {
// 保存之前的状态
const previousStatus = currentStatus;
// 立即更新 UI
setStatus(newStatus);
},
onError: (error, variables) => {
// 发生错误时回滚
}
});
return (
<Switch
checked={status}
onChange={(checked) => mutate(checked)}
/>
);
};
const FileUpload = () => {
const { mutate, isLoading } = useMutation(uploadFile, {
onMutate: (file) => {
// 上传前的验证
if (file.size > maxSize) {
// 会阻止后续代码执行
return new Promise.reject('文件过大')
}
},
onSuccess: (response) => {
message.success('上传成功');
setFileList(prev => [...prev, response.data]);
}
});
return (
<Upload
customRequest={({ file }) => mutate(file)}
loading={isLoading}
>
<Button>上传文件</Button>
</Upload>
);
};
// hooks/useDeleteMutation.ts
export const useDeleteMutation = (options?: MutationOptions) => {
return useMutation(deleteItem, {
onSuccess: () => {
message.success('删除成功');
},
onError: (error) => {
message.error('删除失败:' + error.message);
},
...options
});
};
// 使用
const { mutate } = useDeleteMutation({
onSuccess: () => {
// 额外的成功处理
reload();
}
});
interface Variables {
id: string;
data: Record<string, any>;
}
interface Response {
success: boolean;
data: any;
}
const { mutate } = useMutation<Response, Error, Variables>(
updateData,
{
onSuccess: (response) => {
// response 有完整的类型提示
if (response.success) {
// ...
}
}
}
);
const { mutate } = useMutation(submitData, {
onError: (error) => {
if (error.code === 'VALIDATION_ERROR') {
// 表单验证错误
form.setFields(error.fields);
} else if (error.code === 'NETWORK_ERROR') {
// 网络错误
message.error('网络异常,请重试');
} else {
// 其他错误
message.error('操作失败:' + error.message);
}
}
});
const { mutate, reset, isError } = useMutation(submitForm);
// 在特定情况下重置状态
useEffect(() => {
if (visible) {
reset(); // 弹窗打开时重置状态
}
}, [visible]);
开发效率
代码质量
用户体验
团队协作