女人被做网站,设置网络的网站,我看别人做系统就直接网站下载,制作网站的软件我们尝试使用recoil进行全局状态管理以及axios进行网络请求。
recoil
recoil是facebook官方推出的新的react状态管理方案#xff0c;采用分散管理原子状态的设计模式#xff0c;同时也强调immuteable#xff08;mobx则是mutable#xff09;#xff0c;这与react强调immu…我们尝试使用recoil进行全局状态管理以及axios进行网络请求。
recoil
recoil是facebook官方推出的新的react状态管理方案采用分散管理原子状态的设计模式同时也强调immuteablemobx则是mutable这与react强调immuteable相符合更好的适应react增强组件整体性能。以下是官网的提出的动机 如果只借助react实现全局状态管理通过提升变量或者使用Context 这里是引用出于兼容性和简便性的考虑相比使用外部的全局状态使用 React 内置的状态管理能力是个最佳的选择。 但是 React 有这样一些局限性 组件间的状态共享只能通过将 state 提升至它们的公共祖先来实现但这样做可能导致重新渲染一颗巨大的组件树。 Context 只能存储单一值无法存储多个各自拥有消费者的值的集合。 以上两种方式都很难将组件树的顶层state 必须存在的地方与叶子组件 (使用 state 的地方) 进行代码分割。 Recoil相比于redux、mobx的优势 Recoil 定义了一个有向图 (directed graph)正交同时又天然连结于你的 React 树上。状态的变化从该图的顶点我们称之为 atom开始流经纯函数 (我们称之为 selector) 再传入组件。基于这样的实现 我们可以定义无需模板代码的 API共享的状态拥有与 React 本地 state 一样简单的 get/set 接口 (当然如果需要也可以使用 reducer 等进行封装)。 我们有了与 Concurrent 模式及其他 React 新特性兼容的可能性。 状态的定义是渐进式和分布式的这使代码分割成为可能。 无需修改对应的组件就能将它们本地的 state 用派生数据替换。 无需修改对应的组件就能将派生数据在同步与异步间切换。 我们能将导航视为头等概念甚至可以将状态的转变编码进链接中。 可以很轻松地以可回溯的方式持久化整个应用的状态持久化的状态不会因为应用的改变而丢失。 Recoil采用hook的方式获得或修改状态同时也提供了派生状态类似于computed
使用
在axios进行网络请求时我们实现网络请求时的全局遮罩层加载在axios的拦截器中统一实现而无需每一次请求都需要手动添加提高代码的效率减少不必要的重复工作。
此时就需要一个全局状态来管理遮罩层的隐藏与加载在这里我们通过recoil实现。
使用npm安装axios及recoil
使用Recoil的组件需要使用RecoilRoot组件包裹起来我们在main.tsx中引入RecoilRoot组件然后将其包裹在根组件外
import React from react
import ReactDOM from react-dom/client
import App from ./App.tsx
import {MemoryRouter} from react-router-dom
import {RecoilRoot} from recoilReactDOM.createRoot(document.getElementById(root)!).render(React.StrictModeMemoryRouterRecoilRootApp //RecoilRoot/MemoryRouter/React.StrictMode,
)
接着我们可以新建一个store文件夹定义一个loading.ts文件
import { atom } from recoilexport const loadingState atom({key: loadingState,default: false,
})
recoil通过Atom定义一个状态Atom 是一种新的状态但是和传统的 state 不同它可以被任何组件订阅当一个 Atom 被更新时每个被订阅的组件都会用新的值来重新渲染。
接着我们新建一个api文件夹新建index.ts文件完成axios的配置及loadingState的更新
import axios from axios
import { loadingState } from /store/loading
import { useSetRecoilState } from recoilaxios.defaults.baseURL http://localhost:3000/api
const setLoading useSetRecoilState(loadingState)// 请求拦截器
axios.interceptors.request.use((config) {setLoading(true)//加入token或其他一些操作const token localStorage.getItem(token)if (token) {config.headers.Authorization Bearer ${token}}return config
})// 相应拦截器
axios.interceptors.response.use((res) {setLoading(false)return res
})
其中 useRecoilState类似 useState 的一个 Hook可以取到 atom 的值以及 setter 函数
useSetRecoilState只获取 setter 函数如果只使用了这个函数状态变化不会导致组件重新渲染
useRecoilValue只获取状态
loadingState控制app.tsx中的遮罩层及导航栏 在app.tsx中我们使用了Mask和SpinLoading组件来实现加载效果同时也控制导航栏通过使用useRecoilValuehook得到的flag来控制。
import { Routes,Route,useNavigate,useLocation, Navigate } from react-router-dom
import { TabBar,Popup,Mask,SpinLoading} from antd-mobile
import { tabs } from ./router
import ./App.css
import {useRecoilValue} from recoil
import {loadingState} from ./store/loading
function App() {const pathname useLocation().pathnameconst navigate useNavigate()const setRouteActive (value: string) {console.log(value)navigate(value,{state:1})}const flag useRecoilValueboolean(loadingState)return (Mask visible{flag} classNamemask SpinLoading //MaskRoutes{tabs.map(item (Route key{item.key} path{item.key} element{item.element} /))}Route path/ element{Navigate to/home/Navigate} /Route path* element{div404/div} //RoutesPopup visible{!flag} mask{false}TabBar activeKey{pathname} onChange{value setRouteActive(value)}{tabs.map(item (TabBar.Item key{item.key} icon{item.icon} title{item.title} /))}/TabBar/Popup/)
}export default App
这里我们对之前的路由配置也进行了优化对‘/’路径进行了重定向 Route path/ element{Navigate to/home/Navigate} /同样我们也可以在其他地方引入loadingState比如在home.tsx中
import {Button } from antd-mobile
import { loadingState } from /store/loading
import {useRecoilState} from recoil
export default function Home() {const [flag,setFlag] useRecoilStateboolean(loadingState)return (divButton colorprimary onClick{()setFlag(!flag)}change/Button/div)
}点击按钮前 点击按钮后flag状态被修改遮罩层和loading出现