
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
keepalive-for-react
Advanced tools
A React KeepAlive component like keep-alive in vue
中文 | English
| Package | Version | Description |
|---|---|---|
| keepalive-for-react | Core keepalive functionality | |
| keepalive-for-react-router | React Router integration |
active and inactiveVersion Compatibility:
keepalive-for-react@4.x.xkeepalive-for-react@5.x.xDO NOT use <React.StrictMode />, it CANNOT work with keepalive-for-react in development mode. because it can lead to some unexpected behavior.
In Router only support react-router-dom v6+
npm install keepalive-for-react
yarn add keepalive-for-react
pnpm add keepalive-for-react
# v6+
npm install react-router-dom keepalive-for-react keepalive-for-react-router@1.x.x
# v7+
npm install react-router keepalive-for-react keepalive-for-react-router@2.x.x
// v6+ keepalive-for-react-router@1.x.x
// v7+ keepalive-for-react-router@2.x.x
import KeepAliveRouteOutlet from "keepalive-for-react-router";
function Layout() {
return (
<div className="layout">
<KeepAliveRouteOutlet />
</div>
);
}
or
import { useMemo } from "react";
// v6+
import { useLocation, useOutlet } from "react-router-dom";
// v7
// import { useLocation, useOutlet } from "react-router";
import { KeepAlive, useKeepAliveRef } from "keepalive-for-react";
function Layout() {
const location = useLocation();
const aliveRef = useKeepAliveRef();
const outlet = useOutlet();
// determine which route component to is active
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>
);
}
details see examples/react-router-dom-simple-starter
npm install keepalive-for-react
const 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
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;
/**
* use view transition to animate the component when switching tabs
* @see https://developer.chrome.com/docs/web-platform/view-transitions/
*/
viewTransition?: boolean;
/**
* transition duration default 200
*/
duration?: number;
aliveRef?: RefObject<KeepAliveRef | undefined>;
/**
* max alive time for cache node (second)
* @default 0 (no limit)
*/
maxAliveTime?: number | MaxAliveConfig[];
/**
* enable Activity component from react 19+
* @default false
* Activity component can improve performance, but it will affect the transition effect
* Attention: if enable Activity component, useEffect will trigger when the component is active
*/
enableActivity?: boolean;
}
interface MaxAliveConfig {
match: string | RegExp;
expire: number;
}
useEffectOnActive(() => {
console.log("active");
}, []);
useLayoutEffectOnActive(
() => {
console.log("active");
},
[],
false,
);
// the third parameter is optional, default is false,
// if true, which means the callback will be skipped when the useLayoutEffect is triggered in first render
type definition
interface KeepAliveContext {
/**
* whether the component is active
*/
active: boolean;
/**
* refresh the component
* @param {string} [cacheKey] - The cache key of the component. If not provided, the current cached component will be refreshed.
*/
refresh: (cacheKey?: string) => void;
/**
* destroy the component
* @param {string} [cacheKey] - the cache key of the component, if not provided, current active cached component will be destroyed
*/
destroy: (cacheKey?: string | string[]) => Promise<void>;
/**
* destroy all components
*/
destroyAll: () => Promise<void>;
/**
* destroy other components except the provided cacheKey
* @param {string} [cacheKey] - The cache key of the component. If not provided, destroy all components except the current active cached component.
*/
destroyOther: (cacheKey?: string) => Promise<void>;
/**
* get the cache nodes
*/
getCacheNodes: () => Array<CacheNode>;
}
const { active, refresh, destroy, getCacheNodes } = useKeepAliveContext();
// active is a boolean, true is active, false is inactive
// refresh is a function, you can call it to refresh the component
// destroy is a function, you can call it to destroy the component
// ...
// getCacheNodes is a function, you can call it to get the cache nodes
type definition
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 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} />;
}
install dependencies
pnpm install
build package
pnpm build
FAQs
A react <KeepAlive/> component like <keep-alive/> in vue
The npm package keepalive-for-react receives a total of 2,710 weekly downloads. As such, keepalive-for-react popularity was classified as popular.
We found that keepalive-for-react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.