这篇文章主要讲解了“如何用React-query解决状态管理问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何用React-query解决状态管理问题”吧!
按照来源,前端有两类「状态」需要管理:
用户交互的中间状态
服务端状态
在陈年的老项目中,通常用Redux、Mobx这样的「全局状态管理方案」无差别对待他们。
事实上,他们有很大区别:
用户交互的中间状态
比如组件的isLoading、isOpen,这类「状态」的特点是:
以「同步」的形式更新
「状态」完全由前端控制
「状态」比较独立(不同的组件拥有各自的isLoading)
这类「状态」通常保存在组件内部。
当「状态」需要跨组件层级传递,通常使用Context API。
再大范围的「状态」会使用Redux这样的「全局状态管理方案」。
服务端状态
当我们从服务端请求数据:
function App() { const [data, updateData] = useState(null); useEffect(async () => { const data = await axios.get('/api/user'); updateData(data); }, []) // 处理data }
返回的数据通常作为「状态」保存在组件内部(如App组件的data状态)。
如果是需要复用的通用「状态」,通常将其保存在Redux这样的「全局状态管理方案」中。
这样做有2个坏处:
1.需要重复处理请求中间状态
为了让App组件健壮,我们还需要处理请求中、出错等中间状态:
function App() { const [data, updateData] = useState(null); const [isError, setError] = useState(false); const [isLoading, setLoading] = useState(false); useEffect(async () => { setError(false); setLoading(true); try { const data = await axios.get('/api/user'); updateData(data); } catch(e) { setError(true); } setLoading(false); }, []) // 处理data }
这类通用的中间状态处理逻辑可能在不同组件中重复写很多次。
2.「缓存」的性质不同于「状态」
不同于交互的中间状态,服务端状态更应被归类为「缓存」,他有如下性质:
通常以「异步」的形式请求、更新
「状态」由请求的数据源控制,不由前端控制
「状态」可以由不同组件共享
作为可以由不同组件共享的「缓存」,还需要考虑更多问题,比如:
缓存失效
缓存更新
Redux一把梭固然方便。但是,区别对待不同类型「状态」能让项目更可控。
这里,推荐使用React-Query管理服务端状态。
另一个可选方案是SWR[1]。你可以从这里[2]看到他们的区别
初识React-Query
React-Query是一个基于hooks的数据请求库。
我们可以将刚才的例子用React-Query改写:
import { useQuery } from 'react-query' function App() { const {data, isLoading, isError} = useQuery('userData', () => axios.get('/api/user')); if (isLoading) { return <div>loading</div>; } return ( <ul> {data.map(user => <li key={user.id}>{user.name}</li>)} </ul> ) }
React-Query中的Query指一个异步请求的数据源。
例子中userData字符串就是这个query独一无二的key。
可以看到,React-Query封装了完整的请求中间状态(isLoading、isError...)。
不仅如此,React-Query还为我们做了如下工作:
多个组件请求同一个query时只发出一个请求
缓存数据失效/更新策略(判断缓存合适失效,失效后自动请求数据)
对失效数据垃圾清理
数据的CRUD由2个hook处理:
useQuery处理数据的查
useMutation处理数据的增/删/改
在下面的例子中,点击「创建用户」按钮会发起创建用户的post请求:
import { useQuery, queryCache } from 'react-query'; unction App() { const {data, isLoading, isError} = useQuery('userData', () => axios.get('/api/user')); // 新增用户 const {mutate} = useMutation(data => axios.post('/api/user', data)); return ( <ul> {data.map(user => <li key={user.id}>{user.name}</li>)} <button onClick={() => { mutate({name: 'kasong', age: 99}) }} > 创建用户 </button> </ul> )
但是点击后userData query对应数据不会更新,因为他还未失效。
所以我们需要告诉React-Query,userData query对应的缓存已经失效,需要更新:
import { useQuery, queryCache } from 'react-query'; function App() { // ... const {mutate} = useMutation(userData => axios.post('/api/user', userData), { onSuccess: () => { queryCache.invalidateQueries('userData') } }) // ... }
通过调用mutate方法,会触发请求。
当请求成功后,会触发onSuccess回调,回调中调用queryCache.invalidateQueries,将userData对应的query缓存置为invalidate。
这样,React-Query就会重新请求userData对应query的数据。
总结
通过使用React-Query(或SWR)这样的数据请求库,可以将服务端状态从全局状态中解放出来。
这为我们带来很多好处:
使用通用的hook处理请求中间状态
多余请求合并
针对缓存的更新/失效策略
Redux等「全局状态管理方案」可以更专注于「前端中间状态」处理
感谢各位的阅读,以上就是“如何用React-query解决状态管理问题”的内容了,经过本文的学习后,相信大家对如何用React-query解决状态管理问题这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。