Releases: finedaybreak/keepalive-for-react
Releases · finedaybreak/keepalive-for-react
v5.0.7
v3.0.0
KeepAlive for React
A React KeepAlive component like keep-alive in vue
中文 | English
Features
- Support react-router-dom v6+
- Support React v16+ ~ v18+
- Support Suspense and Lazy import
- Support ErrorBoundary
- Support Custom Container
- Support Switching Animation Transition with className
activeandinactive - Simply implement, without any extra dependencies and hacking ways
Attention
-
DO NOT use <React.StrictMode />, it CANNOT work with keepalive-for-react in development mode. because it can lead to
some unexpected behavior when you use keepalive-for-react's useOnActive hook. -
In Router only support react-router-dom v6+
Install
npm install keepalive-for-reactyarn add keepalive-for-reactpnpm add keepalive-for-reactUsage
in react-router-dom v6+
- install react-router-dom v6+
npm install react-router-dom keepalive-for-react- use KeepAlive in your project
import { KeepAliveRouteOutlet } from "keepalive-for-react";
function Layout() {
return (
<div className="layout">
<KeepAliveRouteOutlet />
</div>
);
}details see examples/react-router-dom-simple-starter
in simple tabs
npm install keepalive-for-reactconst tabs = [
{
key: "tab1",
label: "Tab 1",
component: Tab1,
},
{
key: "tab2",
label: "Tab 2",
component: Tab2,
},
{
key: "tab3",
label: "Tab 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>
);
}details see examples/simple-tabs-starter
KeepAlive Props
type definition
interface KeepAliveProps {
// determine which component to is active
activeCacheKey: string;
children?: KeepAliveChildren;
/**
* max cache count default 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;
}>;
/**
* transition default false
*/
transition?: boolean;
/**
* transition duration default 200
*/
duration?: number;
aliveRef?: RefObject<KeepAliveRef | undefined>;
}Hooks
useEffectOnActive
useEffectOnActive(() => {
console.log("active");
}, []);useLayoutEffectOnActive
useLayoutEffectOnActive(
() => {
console.log("active");
},
[],
false,
);
// the third parameter is optional, default is true,
// which means the callback will be skipped when the useLayoutEffect is triggered in first renderuseKeepAliveContext
type definition
interface KeepAliveContext {
/**
* whether the component is active
*/
active: boolean;
/**
* refresh the component
* @param cacheKey - the cache key of the component,
* if not provided, current active cached component will be refreshed
*/
refresh: (cacheKey?: string) => void;
}const { active, refresh } = useKeepAliveContext();
// active is a boolean, true is active, false is inactive
// refresh is a function, you can call it to refresh the componentuseKeepaliveRef
type definition
interface KeepAliveRef {
refresh: (cacheKey?: string) => void;
destroy: (cacheKey: string) => Promise<void>;
}function App() {
const aliveRef = useKeepaliveRef();
// aliveRef.current is a KeepAliveRef object
// you can call refresh and destroy on aliveRef.current
aliveRef.current?.refresh();
// it is not necessary to call destroy manually, KeepAlive will handle it automatically
aliveRef.current?.destroy();
return <KeepAlive aliveRef={aliveRef}>{/* ... */}</KeepAlive>;
}
// or
function AppRouter() {
const aliveRef = useKeepaliveRef();
// aliveRef.current is a KeepAliveRef object
// you can call refresh and destroy on aliveRef.current
aliveRef.current?.refresh();
aliveRef.current?.destroy();
return <KeepAliveRouteOutlet aliveRef={aliveRef} />;
}Development
install dependencies
pnpm installbuild package
pnpm buildlink package to global
pnpm link --globaltest in demo project
cd demo
pnpm link --global keepalive-for-reactv2.0.12
New Feature in v2.0.12
Now, you can refresh you cached component !!!
in KeepAlive aliveRef
import { useKeepaliveRef } from "keepalive-for-react"
function Example() {
const aliveRef = useKeepaliveRef()
function refresh(){
aliveRef.current?.refresh() // default refresh current showing cached component without the name param
// aliveRef.current?.refresh("your refresh component name")
}
// ...
return <KeepAlive aliveRef={aliveRef} >
...
</KeepAlive>
}in cached component
import {useKeepAliveContext} from 'keepalive-for-react';
function CachedComponent() {
const { refresh } = useKeepAliveContext();
// refresh: (name?: string) => void, refresh the component same as `aliveRef.current?.refresh()`
}v2.0.6
New Release: Version v2.0.6
Introducing new hooks useEffectOnActive, useLayoutEffectOnActive
/**
* a hook that executes a callback function when the active state of the cache component changes.
* The callback can optionally return a cleanup function that will be executed on component unmount or before the callback is executed again.
*
* @param cb A callback function to be executed when the active state changes. It receives the current active state as a parameter. If it returns a function, that function will be used as a cleanup callback.
* @param skipMount If true, the callback (and potentially its cleanup) is not executed on the initial component mount. Defaults to false.
* @param deps Dependencies to be passed to the useEffect hook.
*/
export const useEffectOnActive = (cb: (active: boolean) => void | (() => void), skipMount = false, deps: DependencyList): void => {
const { active } = useCacheComponentContext()
const isMount = useRef<boolean>(false)
useEffect(() => {
if (skipMount && !isMount.current) {
isMount.current = true
return
}
const destroyCb = cb(active)
return () => {
if (isFn(destroyCb)) {
destroyCb()
}
}
}, [active, ...deps])
}
/**
* @name useLayoutEffectOnActive
* a hook that executes a callback function when the active state of the cache component changes.
* The callback can optionally return a cleanup function that will be executed on component unmount or before the callback is executed again.
*
* @param cb A callback function to be executed when the active state changes. It receives the current active state as a parameter. If it returns a function, that function will be used as a cleanup callback.
* @param skipMount If true, the callback (and potentially its cleanup) is not executed on the initial component mount. Defaults to false.
* @param deps Dependencies to be passed to the useLayoutEffect hook.
*/
export const useLayoutEffectOnActive = (cb: (active: boolean) => void | (() => void), skipMount = false, deps: DependencyList): void => {
const { active } = useCacheComponentContext()
const isMount = useRef<boolean>(false)
useLayoutEffect(() => {
if (skipMount && !isMount.current) {
isMount.current = true
return
}
const destroyCb = cb(active)
return () => {
if (isFn(destroyCb)) {
destroyCb()
}
}
}, [active, ...deps])
}v2.0.5
New Release: Version v2.0.5
Introducing new hooks:
useKeepaliveRef
type KeepAliveRef = {
getCaches: () => Array<CacheNode>
removeCache: (name: string) => void
cleanAllCache: () => void
cleanOtherCache: () => void
}import { useKeepaliveRef } from "keepalive-for-react"
function Example() {
const aliveRef = useKeepaliveRef()
function clean(){
aliveRef.current?.cleanAllCache()
}
// ...
return <KeepAlive aliveRef={aliveRef} >
...
</KeepAlive>
}v2.0.0
New Release: Version v2.0.0
Introducing new hooks:
useOnActiveuseKeepAliveContext
Improvements:
- The
useOnActivehook no longer requires thedomRefparameter. useKeepAliveContextnow allows you to access the active state of the cached component and provides adestroymethod to clear the component's cache directly.
