
Product
Socket for Jira Is Now Available
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.
react-activation
Advanced tools
DO NOT use <React.StrictMode />
(React v18+) DO NOT use ReactDOMClient.createRoot, use ReactDOM.render instead, https://github.com/CJY0208/react-activation/issues/225#issuecomment-1311136388
or You can disable autoFreeze to work with createRoot though this may result in performance loss
import { KeepAlive } from 'react-activation'
KeepAlive.defautProps.autoFreeze = false // default 'true'
English | 中文说明
HACK Implementation of the <keep-alive /> function in Vue For React
Please also pay attention to official support <Offscreen /> in React 18.x
More stable <KeepAlive /> function with babel pre-compilation
React v16 / v17 / v18
Preact v10+
Compatible with SSR
yarn add react-activation
# or
npm install react-activation
react-activation/babel plugins in .babelrcThe plugin adds a _nk attribute to each JSX element during compilation to help the react-activation runtime generate an unique identifier by render location base on react-node-key.
{
"plugins": [
"react-activation/babel"
]
}
(0.11.0+) If you don't want to use Babel, it is recommended that each <KeepAlive> declare a globally unique and invariant cacheKey attribute to ensure the stability of the cache, as follows:
<KeepAlive cacheKey="UNIQUE_ID" />
<KeepAlive>Like the <Counter> component in the example
// App.js
import React, { useState } from 'react'
import KeepAlive from 'react-activation'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>count: {count}</p>
<button onClick={() => setCount(count => count + 1)}>Add</button>
</div>
)
}
function App() {
const [show, setShow] = useState(true)
return (
<div>
<button onClick={() => setShow(show => !show)}>Toggle</button>
{show && (
<KeepAlive>
<Counter />
</KeepAlive>
)}
</div>
)
}
export default App
<AliveScope> outer layer at a location that will not be unmounted, usually at the application entranceNote: When used with react-router or react-redux, you need to place <AliveScope> inside <Router> or <Provider>
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { AliveScope } from 'react-activation'
import App from './App'
ReactDOM.render(
<AliveScope>
<App />
</AliveScope>,
document.getElementById('root')
)
ClassComponent works with withActivation decorator
Use componentDidActivate and componentWillUnactivate to correspond to the two states of "activate" and "unactivate" respectively.
FunctionComponent uses the useActivate and useUnactivate hooks respectively
...
import KeepAlive, { useActivate, useUnactivate, withActivation } from 'react-activation'
@withActivation
class TestClass extends Component {
...
componentDidActivate() {
console.log('TestClass: componentDidActivate')
}
componentWillUnactivate() {
console.log('TestClass: componentWillUnactivate')
}
...
}
...
function TestFunction() {
useActivate(() => {
console.log('TestFunction: didActivate')
})
useUnactivate(() => {
console.log('TestFunction: willUnactivate')
})
...
}
...
function App() {
...
return (
{show && (
<KeepAlive>
<TestClass />
<TestFunction />
</KeepAlive>
)}
)
}
...
Add the name attribute to the <KeepAlive> tag that needs to control the cache.
Get control functions using withAliveScope or useAliveController.
drop(name): (drop can only be used for nodes in the cache state. If the node is not cached but needs to clear the cache state, please use refresh)
Unload the <KeepAlive> node in cache state by name. The name can be of type String or RegExp. Note that only the first layer of content that hits <KeepAlive> is unloaded and will not be uninstalled in <KeepAlive>. Would not unload nested <KeepAlive>.
dropScope(name): (dropScope can only be used for nodes in the cache state. If the node is not cached but needs to clear the cache state, please use refreshScope)
Unloads the <KeepAlive> node in cache state by name. The name optional type is String or RegExp, which will unload all content of <KeepAlive>, including all <KeepAlive> nested in <KeepAlive>.
refresh(name):
Refresh the <KeepAlive> node in cache state by name. The name can be of type String or RegExp. Note that only the first layer of content that hits <KeepAlive> is refreshed and will not be uninstalled in <KeepAlive>. Would not refresh nested <KeepAlive>.
refreshScope(name):
Refresh the <KeepAlive> node in cache state by name. The name optional type is String or RegExp, which will refresh all content of <KeepAlive>, including all <KeepAlive> nested in <KeepAlive>.
clear():
will clear all <KeepAlive> in the cache
getCachingNodes():
Get all the nodes in the cache
...
import KeepAlive, { withAliveScope, useAliveController } from 'react-activation'
...
<KeepAlive name="Test">
...
<KeepAlive>
...
<KeepAlive>
...
</KeepAlive>
...
</KeepAlive>
...
</KeepAlive>
...
function App() {
const { drop, dropScope, clear, getCachingNodes } = useAliveController()
useEffect(() => {
drop('Test')
// or
drop(/Test/)
// or
dropScope('Test')
clear()
})
return (
...
)
}
// or
@withAliveScope
class App extends Component {
render() {
const { drop, dropScope, clear, getCachingNodes } = this.props
return (
...
)
}
}
...
Add the when attribute to the <KeepAlive /> tag that needs to control the cache. The value is as follows
when type is Boolean<KeepAlive when={false}>
when type is ArrayThe 1th parameter indicates whether it needs to be cached at the time of uninstallation.
The 2th parameter indicates whether to unload all cache contents of <KeepAlive>, including all <KeepAlive> nested in <KeepAlive>.
// For example:
// The following indicates that it is not cached when uninstalling
// And uninstalls all nested `<KeepAlive>`
<KeepAlive when={[false, true]}>
...
<KeepAlive>
...
<KeepAlive>...</KeepAlive>
...
</KeepAlive>
...
</KeepAlive>
when type is Function (Recommended)The return value is the above Boolean or Array, which takes effect as described above.
The final calculation time of when is adjusted to componentWillUnmount lifecicle of <KeepAlive>, the problem that most of the when do not achieve the expected effect can be avoided.
<KeepAlive when={() => true}>
<KeepAlive when={() => [false, true]}>
Under the same parent node, <KeepAlive> in the same location will use the same cache by default.
For example, with the following parameter routing scenario, the /item route will be rendered differently by id, but only the same cache can be kept.
<Route
path="/item/:id"
render={props => (
<KeepAlive>
<Item {...props} />
</KeepAlive>
)}
/>
Similar scenarios, you can use the id attribute of <KeepAlive> to implement multiple caches according to specific conditions.
<Route
path="/item/:id"
render={props => (
<KeepAlive id={props.match.params.id}>
<Item {...props} />
</KeepAlive>
)}
/>
true by default)<KeepAlive /> would try to detect scrollable nodes in its children, then, save their scroll position automaticlly before componentWillUnactivate and restore saving position after componentDidActivate
If you don't want <KeepAlive /> to do this thing, set saveScrollPosition prop to false
<KeepAlive saveScrollPosition={false} />
If your components share screen scroll container, document.body or document.documentElement, set saveScrollPosition prop to "screen" can save sharing screen container's scroll position before componentWillUnactivate
<KeepAlive saveScrollPosition="screen" />
Pass the children attribute of <KeepAlive /> to <AliveScope /> and render it with <Keeper />
After rendering <Keeper />, the content is transferred to <KeepAlive /> through DOM operation.
Since <Keeper /> will not be uninstalled, caching can be implemented.
<KeepAlive /> needs to pass children to <AliveScope /> , so the rendering of the real content will be slower than the normal situation
Will have a certain impact on the function of strictly relying on the lifecycle order, such as getting the value of ref in componentDidMount, as follows
class Test extends Component {
componentDidMount() {
console.log(this.outside) // will log <div /> instance
console.log(this.inside) // will log undefined
}
render() {
return (
<div>
<div
ref={ref => {
this.outside = ref
}}
>
Outside KeepAlive
</div>
<KeepAlive>
<div
ref={ref => {
this.inside = ref
}}
>
Inside KeepAlive
</div>
</KeepAlive>
</div>
)
}
}
The above error in ClassComponent can be fixed by using the withActivation high-level component
FunctionComponent currently has no processing method, you can use setTimeout or nextTick to delay ref getting behavior
@withActivation
class Test extends Component {
componentDidMount() {
console.log(this.outside) // will log <div /> instance
console.log(this.inside) // will log <div /> instance
}
render() {
return (
<div>
<div
ref={ref => {
this.outside = ref
}}
>
Outside KeepAlive
</div>
<KeepAlive>
<div
ref={ref => {
this.inside = ref
}}
>
Inside KeepAlive
</div>
</KeepAlive>
</div>
)
}
}
Destructive impact on Context
after react-actication@0.8.0 with react@16.3+, this question has been automatic fixed
react-actication@0.8.0 with react@17+ you Need to make the following changes to achieve automatic repair
import { autoFixContext } from 'react-activation'
autoFixContext(
[require('react/jsx-runtime'), 'jsx', 'jsxs', 'jsxDEV'],
[require('react/jsx-dev-runtime'), 'jsx', 'jsxs', 'jsxDEV']
)
Versions below react-actication@0.8.0 need to be repaired manually, refer to the following
Problem reference: https://github.com/StructureBuilder/react-keep-alive/issues/36
<Provider value={1}>
{show && (
<KeepAlive>
<Consumer>
{(
context // Since the rendering level is broken, the context cannot be obtained here.
) => <Test contextValue={context} />}
</Consumer>
</KeepAlive>
)}
<button onClick={toggle}>toggle</button>
</Provider>
Choose a repair method
Create Context using createContext exported from react-activation
Fix the affected Context with fixContext exported from react-activation
...
import { createContext } from 'react-activation'
const { Provider, Consumer } = createContext()
...
// or
...
import { createContext } from 'react'
import { fixContext } from 'react-activation'
const Context = createContext()
const { Provider, Consumer } = Context
fixContext(Context)
...
Affects the functionality that depends on the level of the React component, as follows
withRouter/hooks of react-routerFAQs
<KeepAlive /> for React like <keep-alive /> in vue
The npm package react-activation receives a total of 11,326 weekly downloads. As such, react-activation popularity was classified as popular.
We found that react-activation 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.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.