React SWR: 让请求自动cache

现代的 hooks 模型
在用户体验上,前端依然非常依赖和后端之间建立的网络链接。在网络环境良好的情况下,大部分 Web App 都可以提供较好的用户体验。但是随着移动化的浪潮,前端的 App 也越来越多被应用在小程序、h5 等移动环境中,而移动网络的不稳定性和 Web App 的即时渲染,都极大地影响了 Web App 的体验。

通过请求 hooks 对于请求的优化,前端应用更加独立。因为存在 cacheKey、Refetching 等机制,现在我们可以有新的角度去看待 Web App。这个时代下,Web App 更加独立,可以自身缓存一定的数据,也可以更快地响应用户的操作。通过增加静默请求和减少页面全刷新,使网络延迟和数据更新趋于无感。而这一点,hooks 和 diff 机制配合得天衣无缝。

mutate(key)和 mutate()
在 React SWR 中,mutate
方法有两种调用方式:mutate(key)
和 mutate()
。它们的主要区别在于作用范围和使用场景。以下是详细的解释:
1. mutate(key)
mutate(key)
是一个全局方法,用于操作特定的缓存键(key)。你可以通过指定 key
来精确地操作某个缓存数据。
参数
key
:指定要操作的缓存键。data
(可选):如果提供,可以直接更新缓存数据。options
(可选):配置选项,例如{ revalidate: true }
。
作用范围
- 全局作用:
mutate(key)
作用于全局缓存,可以跨组件使用。 - 精确操作:通过指定
key
,可以精确地操作某个缓存数据。
示例
import useSWR, { mutate } from 'swr';
const fetcher = url => fetch(url).then(res => res.json());
function MyComponent() {
const { data, error } = useSWR('/api/data', fetcher);
const updateData = async newData => {
try {
// 调用 update API
await fetch('/api/update', {
method: 'POST',
body: JSON.stringify(newData),
headers: { 'Content-Type': 'application/json' },
});
// 重新验证指定的缓存键
mutate('/api/data');
} catch (err) {
console.error('Update failed:', err);
}
};
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return (
<div>
<div>{JSON.stringify(data)}</div>
<button onClick={() => updateData({ key: 'value' })}>Update Data</button>
</div>
);
}
2. mutate()
mutate()
是一个绑定到 useSWR
的方法,用于操作当前组件中使用的缓存数据。它不需要显式指定 key
,因为 key
已经在 useSWR
中定义。
参数
data
(可选):如果提供,可以直接更新缓存数据。options
(可选):配置选项,例如{ revalidate: true }
。
作用范围
- 局部作用:
mutate()
作用于当前组件中使用的缓存数据。 - 简化操作:不需要显式指定
key
,直接操作当前组件的缓存。
示例
import useSWR, { mutate } from 'swr';
const fetcher = url => fetch(url).then(res => res.json());
function MyComponent() {
const { data, error, mutate } = useSWR('/api/data', fetcher);
const updateData = async newData => {
try {
// 调用 update API
await fetch('/api/update', {
method: 'POST',
body: JSON.stringify(newData),
headers: { 'Content-Type': 'application/json' },
});
// 重新验证当前组件的缓存数据
mutate();
} catch (err) {
console.error('Update failed:', err);
}
};
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return (
<div>
<div>{JSON.stringify(data)}</div>
<button onClick={() => updateData({ key: 'value' })}>Update Data</button>
</div>
);
}
总结
-
mutate(key)
:- 全局作用:可以跨组件操作指定的缓存键。
- 精确操作:需要显式指定
key
。 - 适用场景:当你需要在多个组件中操作同一个缓存键时,或者需要操作全局缓存时。
-
mutate()
:- 局部作用:只作用于当前组件中使用的缓存数据。
- 简化操作:不需要显式指定
key
。 - 适用场景:当你只需要在当前组件中操作缓存数据时,使用
mutate()
更为方便。
选择哪种方式取决于你的具体需求。如果需要跨组件操作缓存,建议使用 mutate(key)
;如果只需要在 当前组件中操作缓存,使用 mutate()
更为简洁。
revalidate 是干什用的?
在 React SWR 中,revalidate
是一个非常重要的选项,用于控制数据的重新验证行为。它允许你手动触发对缓存数据的重新获取,从而确保数据的最新性。
作用
revalidate
的主要作用是强制重新获取数据,即使数据已经存在于缓存中。这在以下几种场景中非常有用:
- 数据更新后:当你通过
update API
修改了数据,需要重新获取最新的数据时。 - 手动刷新:用户触发了手动刷新操作,需要重新获取数据。
- 定时刷新:在某些情况下,你可能希望定期重新获取数据以保持数据的最新性。
使用方法
revalidate
可以在 mutate
方法中使用,也可以在 useSWR
的配置中使用。
1. 在 mutate
中使用 revalidate
当你调用 mutate
方法时,可以通过 options
参数设置 revalidate
为 true
,从而触发重新获取数据。
import useSWR, { mutate } from 'swr';
const fetcher = url => fetch(url).then(res => res.json());
function MyComponent() {
const { data, error } = useSWR('/api/data', fetcher);
const updateData = async newData => {
try {
// 调用 update API
await fetch('/api/update', {
method: 'POST',
body: JSON.stringify(newData),
headers: { 'Content-Type': 'application/json' },
});
// 重新验证数据
mutate('/api/data', undefined, { revalidate: true });
} catch (err) {
console.error('Update failed:', err);
}
};
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return (
<div>
<div>{JSON.stringify(data)}</div>
<button onClick={() => updateData({ key: 'value' })}>Update Data</button>
</div>
);
}
2. 在 useSWR
中使用 revalidate
你也可以在 useSWR
的配置中设置 revalidate
选项,从而控制数据的自动重新验证行为。
import useSWR from 'swr';
const fetcher = url => fetch(url).then(res => res.json());
function MyComponent() {
const { data, error, mutate } = useSWR('/api/data', fetcher, {
revalidateOnMount: true, // 每次组件加载时重新验证
revalidateOnFocus: true, // 窗口重新聚焦时重新验证
revalidateOnReconnect: true, // 网络重新连接时重新验证
});
const updateData = async newData => {
try {
// 调用 update API
await fetch('/api/update', {
method: 'POST',
body: JSON.stringify(newData),
headers: { 'Content-Type': 'application/json' },
});
// 重新验证数据
mutate();
} catch (err) {
console.error('Update failed:', err);
}
};
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return (
<div>
<div>{JSON.stringify(data)}</div>
<button onClick={() => updateData({ key: 'value' })}>Update Data</button>
</div>
);
}
常见的 revalidate
选项
revalidateOnMount
:组件加载时是否重新验证数据。默认值为true
。revalidateOnFocus
:窗口重新聚焦时是否重新验证数据。默认值为true
。revalidateOnReconnect
:网络重新连接时是否重新验证数据。默认值为true
。revalidateIfStale
:如果数据过期(isStale
为true
),是否重新验证数据。默认值为true
。revalidateOnInterval
:设置一个时间间隔(毫秒),每隔这个时间重新验证数据。例如:revalidateOnInterval: 30000
(每 30 秒重新验证一次)。
总结
revalidate
是 React SWR 中一个非常强大的功能,用于控制数据的重新验证行为。通过合理使用 revalidate
,你可以确保数据的最新性,同时避免不必要的网络请求,提升应用的性能和用户体验。