vite react引入react-activation实现

714 阅读3分钟

背景

引用了路由页面的跳转react-router-dom,页面切换过程中未有堆栈路由支持,故在众多实现方式中选中了react-activation,不过它的实现是对组件进行缓存(也就成为后面报错后一直纠结的点),而不是路由缓存. 不过还是可以支持业务优化的效果!

实现

直接参考文档即可,还是很详细的,这边主要说说避开的坑

问题解决

报错: Cannot create property 'name' on string 'react-activation/babel'

按照文档配置后,发现原来如果引用了博主提供的react-activation/babel在本地运行时没问题的,但是打包后就会出现以上的报错。解决方式参考,主要的问题是需要对vite单独做兼容引用,而原本的babel是对webpack的使用

报错: useLocation() may be used only in the context of a component.

已经按照了文档配置了一遍后,一开始以为插件是组件缓存,如果我在路由表配置成如下

    <Route path="/" element={
      <KeepAlive name='index' key="index" navigate={useNavigate()}><Navigate to="/index" /></KeepAlive>
    }/>

那可能影响路由的编译,于是恢复成原有路由表格式,只保留组件缓存的页面,发现跳过去也会出现这个问题😩😩😩,显然不是配置问题(因为单独跳到缓存的组件也会报错,故基础配置问题出现)

通过作者了解

 <Provider store={store}>
      <div>
        <React.Suspense >
          <BrowserRouter>
            <AliveScope>
              <RouterComponent />
            </AliveScope>
          </BrowserRouter>
        </React.Suspense>
      </div>
    </Provider>

还需在router表中再嵌套多一层解决AliveScope才可以正常运行,一开始以为在App.tsx已经有AliveScope嵌套,所以以为不用了。

项目实现的思考

基于只对组件缓存而不是路由缓存的问题。如果从组件要引生到页面缓存,那么我们需要对KeepAlive区分好唯一值key,在跳转的时候KeepAlive就根据key值去区分是否当前已经有没缓存。

选择这个插件的原因也就是刷新页面后组件缓存就不存在了,对PC实现效果很友好

路由表设计

部分页面可以在路由中以组件方式存在缓存,定好key值,那么可以实现,只要对要缓存的路由KeepAlive包裹即可

//index
import Activation,{ KeepAlive,AliveScope }from 'react-activation'
const RouterComponent:any = () => (
  <Routes>
    <Route path="/" element={
      <KeepAlive name='index' key="index" navigate={useNavigate()}><Navigate to="/index" /></KeepAlive>
    }/>
</Routes>
//路由表,我还是有用懒加载去实现
{
    pathname: '/mine',
    name: 'Mine',
    component: ReactLazilyComponent(() => import('@/pages/mine'))
},

BrowserRouter 的写法

参考如上问题二即可,内嵌多AliveScope,在app.tsx也是需要

<AliveScope>
    <App />
</AliveScope>

页面设计

如果遇上详情页,同样的路由,只是拼接携带的参数不同,那么在routes表中是无法解决的,毕竟,路由表中只能接收/:id的值,很多时候往往我们设计不是如此,比如?id=1&type=1这样的方式

这边是直接通过将页面的index.jsx文件提取一个单独的文件,直接在用Activation包裹住,由于KeepAlive中的key值会被插件加上前缀重新定义的,所以很难定位到,可是name值不变,故运用不会被改变的name值去做处理

// home/index
import Activation,{ useActivate , useAliveController } from 'react-activation'
const GeneralPages = () => {
  const [search, setSearch] = useSearchParams()
  import { useSearchParams } from 'react-router-dom'
  const key = search.get('type')
  return (
    <Activation 
      name={key} //必须要的通过它去清楚缓存
      id={key}
      key={key} //必须要的这个记录缓存是否重复
      >
        <GeneralPagesIndex/>
    </Activation>
  )
}
export default GeneralPages

//home/GeneralPagesIndex
//如果你是函数式开发,并且你是在原有代码上做缓存,你可以直接全部拷贝过去,在通过组件引用的方式读取
const GeneralPagesIndex = () => {
//超级多内容的呃
}