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,你可以确保数据的最新性,同时避免不必要的网络请求,提升应用的性能和用户体验。