说起React状态管理方案,很多人的第一反应就是Redux。为什么Redux如此出名,个人观点,2个原因:它出现的早,当时社区还没有更好的状态管理方案,有React核心团队的加持。Redux作者“Dan”在开发出第一版Redux后加入了React团队。另一位合著者“Andrew”也来自React核心团队。Dan的适时出现和名气,催生了Redux相关生态在社区的快速发展,也成为了很多前端团队的标配。谈到状态管理,你通常会谈些什么?谈到“状态管理”,通常会从“广度”和“深度”两个方面来谈。从广度上来说,它之后出现的解决方案似乎都在对标Redux,提出自己独特的解决方案。例如:对比Redux的单向数据流,Mobx使用双向数据绑定对标Redux的“全局状态”概念,recoil提出“原子状态”的概念。在深度上,Redux社区不断扩大,并且基于Redux的中间件应运而生。比如Redux-Saga。在中间件之上,出现了更全面的解决方案,比如基于Redux-Saga的DVA。除了这两个纬度之外,还有其他的视角吗?其实我们可以从问题的本质入手。前端,需要什么状态?从页面交互的角度来看,状态的来源有两种:IO操作缓存数据用户交互的中间状态IO操作缓存数据前端最常见的IO操作就是向服务端请求数据。如果不使用“状态管理”方案,常见的方式是请求数据并保存在组件状态中,如:functionApp(){const[data,updateData]=useState(null);useEffect(()=>{fetchData('/api/user').then(data=>updateData(data))},[])//处理数据}当使用Redux等“状态管理”解决方案时,请求的数据将被序列化并保存在“全局状态”中间。用户交互的中间状态交互的中间状态,如isLoading和isOpen,也存储在组件内部。当是一个可重用的组件,或者状态需要跨组件层级传递时,通常会用到ContextAPI。更广泛的州将使用“州管理”方案。可见,无论是“IO操作缓存的数据”还是“用户交互的中间状态”,常规的解决方案是:一视同仁。这又回到了讨论“广度”(使用哪个状态)和“深度”(使用这个状态管理解决方案的深度)。但实际上,这两种状态的特点是不同的。处理缓存的状态管理对于第一种情况,无论是服务器请求,localStorage,indexedDB,本质上都可以归为缓存。因此,相比于Redux等常规的状态管理方案,缓存处理方案可能更适合。对于缓存,常见的需求是:数据状态、加载?加载完成?发生错误?缓存失效后更新缓存数据的复用在React技术栈中,SWR和react-query是优秀的解决方案。这里有一个SWR的例子:对于刚才的例子:functionApp(){const[data,updateData]=useState(null);useEffect(()=>{fetchData('/api/user').then(data=>updateData(data))},[])//处理数据}SWR使用useSWR解决方案:functionApp(){const{data,error}=useSWR('/api/user',fetcher)if(error)return
