@hhhgamehhh/keepalive-for-react
v1.0.0
Published
A react <KeepAlive/> component like <keep-alive/> in vue
Downloads
213
Maintainers
Readme
English | 中文
特性
- 支持react-router-dom v6+
- 支持React v16+ ~ v18+
- 支持Suspense和懒加载导入
- 支持错误边界
- 支持自定义容器
- 支持使用className
active
和inactive
进行切换动画过渡 - 简单实现,无需任何额外依赖和hack方式
注意事项
请勿使用 <React.StrictMode />,它在开发模式下无法与keepalive-for-react一起工作。因为它可能会导致一些意外行为。
在路由中仅支持react-router-dom v6+
安装
npm install keepalive-for-react
yarn add keepalive-for-react
pnpm add keepalive-for-react
使用
在react-router-dom v6+中
- 安装react-router-dom v6+
npm install react-router-dom keepalive-for-react
- 在项目中使用KeepAlive
import { KeepAliveRouteOutlet } from "keepalive-for-react";
function Layout() {
return (
<div className="layout">
<KeepAliveRouteOutlet />
</div>
);
}
或者
import { useMemo } from "react";
import { useLocation } from "react-router-dom";
import { KeepAlive, useKeepAliveRef } from "keepalive-for-react";
function Layout() {
const location = useLocation();
const aliveRef = useKeepAliveRef();
const outlet = useOutlet();
// 确定哪个路由组件处于活动状态
const currentCacheKey = useMemo(() => {
return location.pathname + location.search;
}, [location.pathname, location.search]);
return (
<div className="layout">
<MemoizedScrollTop>
<KeepAlive transition aliveRef={aliveRef} activeCacheKey={currentCacheKey} max={18}>
<Suspense fallback={<LoadingArea />}>
<SpreadArea>{outlet}</SpreadArea>
</Suspense>
</KeepAlive>
</MemoizedScrollTop>
</div>
);
}
详情请参见 examples/react-router-dom-simple-starter
在简单标签页中
npm install keepalive-for-react
const tabs = [
{
key: "tab1",
label: "标签1",
component: Tab1,
},
{
key: "tab2",
label: "标签2",
component: Tab2,
},
{
key: "tab3",
label: "标签3",
component: Tab3,
},
];
function App() {
const [currentTab, setCurrentTab] = useState<string>("tab1");
const tab = useMemo(() => {
return tabs.find(tab => tab.key === currentTab);
}, [currentTab]);
return (
<div>
{/* ... */}
<KeepAlive transition={true} activeCacheKey={currentTab} exclude={["tab3"]}>
{tab && <tab.component />}
</KeepAlive>
</div>
);
}
详情请参见 examples/simple-tabs-starter
KeepAlive 属性
类型定义
interface KeepAliveProps {
// 确定哪个组件处于活动状态
activeCacheKey: string;
children?: KeepAliveChildren;
/**
* 最大缓存数量 默认10
*/
max?: number;
exclude?: Array<string | RegExp> | string | RegExp;
include?: Array<string | RegExp> | string | RegExp;
onBeforeActive?: (activeCacheKey: string) => void;
customContainerRef?: RefObject<HTMLDivElement>;
cacheNodeClassName?: string;
containerClassName?: string;
errorElement?: ComponentType<{
children: ReactNode;
}>;
/**
* 过渡效果 默认false
*/
transition?: boolean;
/**
* 过渡时间 默认200ms
*/
duration?: number;
aliveRef?: RefObject<KeepAliveRef | undefined>;
}
Hooks
useEffectOnActive
useEffectOnActive(() => {
console.log("active");
}, []);
useLayoutEffectOnActive
useLayoutEffectOnActive(
() => {
console.log("active");
},
[],
false,
);
// 第三个参数是可选的,默认为true,
// 表示在首次渲染时触发useLayoutEffect时会跳过回调
useKeepAliveContext
类型定义
interface KeepAliveContext {
/**
* 组件是否处于活动状态
*/
active: boolean;
/**
* 刷新组件
* @param {string} [cacheKey] - 组件的缓存键。如果未提供,将刷新当前缓存的组件。
*/
refresh: (cacheKey?: string) => void;
/**
* 销毁组件
* @param {string} [cacheKey] - 组件的缓存键,如果未提供,将销毁当前活动的缓存组件。
*/
destroy: (cacheKey?: string | string[]) => Promise<void>;
/**
* 销毁所有组件
*/
destroyAll: () => Promise<void>;
/**
* 销毁除提供的cacheKey外的其他组件
* @param {string} [cacheKey] - 组件的缓存键。如果未提供,将销毁除当前活动缓存组件外的所有组件。
*/
destroyOther: (cacheKey?: string) => Promise<void>;
/**
* 获取缓存节点
*/
getCacheNodes: () => Array<CacheNode>;
}
const { active, refresh, destroy, getCacheNodes } = useKeepAliveContext();
// active 是一个布尔值,true表示活动,false表示非活动
// refresh 是一个函数,你可以调用它来刷新组件
// destroy 是一个函数,你可以调用它来销毁组件
// ...
// getCacheNodes 是一个函数,你可以调用它来获取缓存节点
useKeepAliveRef
类型定义
interface KeepAliveRef {
refresh: (cacheKey?: string) => void;
destroy: (cacheKey?: string | string[]) => Promise<void>;
destroyAll: () => Promise<void>;
destroyOther: (cacheKey?: string) => Promise<void>;
getCacheNodes: () => Array<CacheNode>;
}
function App() {
const aliveRef = useKeepAliveRef();
// aliveRef.current 是一个 KeepAliveRef 对象
// 你可以在 aliveRef.current 上调用 refresh 和 destroy
aliveRef.current?.refresh();
// 通常不需要手动调用 destroy,KeepAlive 会自动处理
aliveRef.current?.destroy();
return <KeepAlive aliveRef={aliveRef}>{/* ... */}</KeepAlive>;
}
// 或者
function AppRouter() {
const aliveRef = useKeepAliveRef();
// aliveRef.current 是一个 KeepAliveRef 对象
// 你可以在 aliveRef.current 上调用 refresh 和 destroy
aliveRef.current?.refresh();
aliveRef.current?.destroy();
return <KeepAliveRouteOutlet aliveRef={aliveRef} />;
}
开发
安装依赖
pnpm install
构建包
pnpm build
链接包到全局
pnpm link --global
在演示项目中测试
cd demo
pnpm link --global keepalive-for-react