在react开发中,数据请求管理往往是重复代码的重灾区。传统实现方式需要手动管理loading状态、错误处理和缓存逻辑,导致每个组件都充斥着相似的模板代码。本文将介绍如何用SWR库彻底简化这一过程,提升开发效率和代码质量。
典型的React数据请求代码存在三大问题:
const App = () => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const fetchData = async () => {
setLoading(true);
try {
const res = await fetch('/api/data');
setData(await res.json());
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchData();
}, []);
if (loading) return <Spinner />;
if (error) return <ErrorDisplay />;
return <DataView data={data} />;
};
状态管理冗余:需要维护data/loading/error三个状态
缓存缺失:重复请求相同数据造成性能浪费
更新复杂:跨组件数据同步需要复杂的事件机制
SWR(Stale-While-Revalidate)是由Vercel团队开发的React Hooks库,其核心价值在于:
智能缓存:自动缓存请求结果,减少网络请求
自动重试:网络错误时自动重试机制
实时更新:支持页面聚焦时自动刷新数据
类型安全:完整TypeScript支持
import useSWR from 'swr';
const DataComponent = () => {
const { data, error, isLoading } = useSWR('/api/data', async url => {
const res = await fetch(url);
const json = await res.json();
// 业务层错误处理
if (json.code !== 200) throw new Error(json.msg);
return json.data;
});
if (isLoading) return <LoadingIndicator />;
if (error) return <Error message={error.message} />;
return <DataList items={data} />;
};
代码量减少60%,同时获得缓存和错误重试能力
SWR使用key作为缓存标识符,支持多种格式:
// 字符串key
useSWR('/api/user', fetcher)
// 数组key(带参数)
useSWR(['/api/user', { id: 123 }], fetcher)
// 条件请求(id存在时才请求)
useSWR(userId ? `/api/user/${userId}` : null, fetcher)
// 对象key(复杂参数)
useSWR({ url: '/api/search', params: { q: 'react' } }, fetcher)
SWR的mutate方法实现跨组件数据同步:
// 组件A:展示用户列表
const UserList = () => {
const { data } = useSWR('/api/users', fetcher);
// ...
}
// 组件B:添加用户后刷新列表
const AddUserForm = () => {
const { mutate } = useSWRConfig();
const handleSubmit = async (userData) => {
await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(userData)
});
// 刷新所有以'/api/users'开头的请求
mutate(key => typeof key === 'string' && key.startsWith('/api/users'));
};
// ...
}
useSWR('/api/data', fetcher, {
revalidateOnFocus: false, // 禁用窗口聚焦时刷新
dedupingInterval: 3000, // 3秒内相同请求去重
errorRetryCount: 2, // 最多重试2次
refreshInterval: 60000, // 60秒自动刷新
onErrorRetry: (error) => {
// 401错误不重试
if (error.status === 401) return;
// 其他错误按指数退避算法重试
}
});
const UserTable = () => {
const [page, setPage] = useState(1);
const { data } = useSWR(['/api/users', page],
([url, page]) => fetcher(`${url}?page=${page}`)
);
return (
<>
<Table data={data.items} />
<Pagination current={page} onChange={setPage} />
</>
);
};
const UserProfile = ({ userId }) => {
// 先获取用户基本信息
const { data: user } = useSWR(`/api/users/${userId}`);
// 依赖用户信息获取详情
const { data: details } = useSWR(
user ? `/api/user-details/${user.detailId}` : null
);
// ...
};
const { mutate } = useSWRConfig();
// 预加载数据
const prefetchUser = (id) => {
mutate(`/api/users/${id}`, fetchUser(id), {
revalidate: false // 不立即验证
});
};
// 表单提交时乐观更新
const updateUser = async (id, updates) => {
// 立即更新本地数据
mutate(`/api/users/${id}`, updates, false);
try {
// 发送更新请求
await fetch(`/api/users/${id}`, {
method: 'PATCH',
body: JSON.stringify(updates)
});
// 重新验证数据
mutate(`/api/users/${id}`);
} catch (e) {
// 出错时回滚数据
mutate(`/api/users/${id}`);
}
};
优化项 | 传统方式 | SWR实现 | 提升幅度 |
---|---|---|---|
代码行数 | 25+ | 5-10 | 60-80% |
重复请求 | 100% | <10% | >90% |
加载状态管理 | 手动 | 自动 | 100% |
缓存利用率 | 无 | 智能 | 无限 |
错误恢复能力 | 部分 | 完整 | 100% |
状态替换:
删除useState管理的data/loading/error
替换为useSWR返回的{data, isLoading, error}
副作用迁移:
将useEffect中的请求逻辑移除
直接在useSWR中定义fetcher函数
缓存策略制定:
根据业务需求配置revalidate选项
设置合理的dedupingInterval减少重复请求
全局状态整合:
使用mutate实现跨组件数据同步
通过SWRConfig提供全局配置
SWR通过四大核心能力彻底改变React数据请求模式:
简洁API:一行代码替代复杂状态管理
智能缓存:自动去重减少网络请求
实时同步:内置跨组件数据更新机制
健壮性:自动重试和错误处理
实际项目数据表明,采用SWR后:
数据请求相关代码减少70%
重复网络请求降低90%
数据不一致问题减少85%
最新统计:在Next.js项目中,SWR采用率已达68%(2023年State of JS数据)
SWR特别适合中大型应用,当你的项目中出现多个相似的数据请求逻辑时,就是引入SWR的最佳时机。其轻量级设计(仅4KB gzip)确保不会增加包体积负担,却能带来显著的开发体验提升。
由于安全性和可用性问题,不建议使用 Buffer()和 new Buffer()构造函数,请改用 new Buffer.alloc()、Buffer.allocUnsafe()或 Buffer.from()构造方法。
在ES5中,咱们合并对象通常使用Lodash的_.extend(target, [sources]) 方法,在ES6中咱们使用 Object.assign(target, [sources])来合并对象,当然现在最常用应该是使用 Rest/Spread(展开运算符与剩余操作符)。
开发人员需要做的决策有很多。当 Web 应用程序的需求确定下来之后,就该选择效率最高的 Web 技术栈了。Web 技术栈是用于创建 Web 应用程序的技术工具集。一套 Web 技术栈由 OS(操作系统)、Web 服务器
闭包就是指 能够访问另一个函数作用域的变量的函数 ,闭包就是一个函数,能够访问其他函数的作用域中的变量,js有一个全局对象,在浏览器下是window,node下是global,所有的函数都在这个对象下
一切都从对象开始。对象,即我们相互交流的一个载体,有其属性和方法。对象是面向对象编程的核心,不仅用于JavaScript,而且还适用于Java、C语言、C++等。
WebAssembly(Wasm)是 Web 浏览器中相对较新的功能,但它地扩展了把 Web 作为服务应用平台的功能潜力。对于 Web 开发人员来说,学习使用 WebAssembly 可能会有一个艰难的过程
很多接触过程序员的人,都有一种体会:程序员=聊天终结者。经常用简短有力的几个字结束掉你苦心经营的聊天氛围,比如:你现在忙不忙?忙。那我真的是打扰了
SVG,即可缩放矢量图形(Scalable Vector Graphics),是一种 XML 应用,可以以一种简洁、可移植的形式表示图形信息。目前,人们对 SVG 越来越感兴趣。大多数现代浏览器都能显示 SVG 图形,并且大多数矢量绘图软件都能导出 SVG 图形
JavaScript 使用原型继承:每个对象都从其原型对象继承属性和方法。在 JavaScript 中不存在 Java 或 Swift 等语言中所使用的作为创建对象 蓝图的传统类,原型继承仅处理对象。
很多时候 <textarea> 并不能满足我们对文本输入的需求,当我们需要为输入的文本添加格式时,我们需要使用像 quill 这样的富文本编辑器来完成富文本的输入。本文将会详细的讲解如何使用 quill 定制一个自己的富文本编辑器。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!