<KeepAlive>
is a component that maintains component state and avoids repeated re-rendering.
- Only based on
React Fiber
andReact Hooks
. - Triggers original class component life circle.
- Triggers original effect hooks.
- Supports context updates.
- Supports multiple
keep-alive
. - Supports
react-dom
v16.8+. - Supports
react-dom
v17. - Supports
react-dom
v18.
npm install --save react-fiber-keep-alive
import React from 'react';
import ReactDOM from 'react-dom';
import KeepAlive from 'react-fiber-keep-alive';
const root = document.getElementById('root');
ReactDOM.render((
<KeepAlive.Provider value={root}>
...
<KeepAlive name="test">
<YourComponent />
</KeepAlive>
...
</KeepAlive.Provider>
), root);
-
Provide
root
container element.<KeepAlive.Provider value={container}>
- Must be the root container of
render()
. - If not provided,
keep-alive
will be disabled.
- Must be the root container of
-
Wrap your component with
<KeepAlive>
<KeepAlive name="unique-key"> <YourComponent /> </KeepAlive>
- prop "name" is a required unique string used to identify the cache.
- prop "ignore" is a optional boolean used to bypass and clear the cache. (since 0.5.0)
- prop "onRead(name: string): void" is a optional callback after cache applied. (since 0.7.0)
- prop "onSave(name: string): void" is a optional callback after cache saved. (since 0.7.0)
-
Wrap your component with
keepLive()
.import { keepAlive } from 'react-fiber-keep-alive'; const NewComponent = keepAlive(YourComponent, (props) => { // props: the income props for `<YourComponent>` // you can use react hooks here return `unique-key`; // or return { name: `unique-key`, // other props for `<KeepAlive>` }; });
-
Hook:
useIgnoreKeepAlive()
returns a cache cleaner function.import { useIgnoreKeepAlive } from 'react-fiber-keep-alive'; const ignoreCache = useIgnoreKeepAlive(); ignoreCache(`unique-key`);
-
If the
render()
of class component has side effects.import { markClassComponentHasSideEffectRender } from 'react-fiber-keep-alive'; markClassComponentHasSideEffectRender(ClassComponent); // Example: class Test extends React.Component { render() { // side effect here, ex: emit event here. return null; } } markClassComponentHasSideEffectRender(Test);
-
If no need to trigger the effect hook while remounting.
import { markEffectHookIsOnetime } from 'react-fiber-keep-alive'; markEffectHookIsOnetime(effectHook); // Example: React.useEffect(markEffectHookIsOnetime(() => { // do something }), []); React.useLayoutEffect(markEffectHookIsOnetime(() => { // do something }), []);
-
KeepAlive.Context
(since 0.7.0)import * as React from 'react'; import KeepAlive, { Context, KeepAliveCache } from 'react-fiber-keep-alive'; import LRUCache from 'lru-cache'; /// Example: Use LRU to manage the cache const YourKeepAliveProvider: React.FC<{ children: React.ReactNode; value: null | HTMLElement; }> = (props) => { const container = props.value; const context: Context = React.useMemo(() => { if (!container) { return []; } const caches = new LRUCache<string, KeepAliveCache>({ max: 10, }); return [container, caches, new Map()]; }, []); return ( <KeepAlive.Context.Provider value={context}> {props.children} </KeepAlive.Context.Provider> ); };
- Be careful the global side effects. (ex: insert global style)
- Do not use
<KeepAlive>
under the<React.StrictMode>
. - Recursive
<KeepAlive>
handled by top level<KeepAlive>
. - If the
container
changed inReactDOM.createPortal(children, container)
.- All saved sub tree state will be lost.
- Errors from
react-devtools
after<KeepAlive>
remounted.- Try force refresh the components tree. (ex: updates components filter)
-
render(children, container)
-
hydrate(children, container)
-
createRoot(container).render(children)
-
hydrateRoot(container, children)
-
Component.getDerivedStateFromProps()
-
Component.getDerivedStateFromError()
-
instance.componentDidMount()
-
instance.getSnapshotBeforeUpdate()
-
instance.componentDidUpdate()
-
instance.componentWillUnmount()
-
instance.render()
-
useContext()
-
useCallback()
-
useEffect()
-
useImperativeHandle()
-
useLayoutEffect()
-
useMemo()
-
useRef()
-
useState()
-
useDebugValue()
-
useDeferredValue()
(since v18) -
useId()
(since v18) -
useInsertionEffect()
(since v18) -
useSyncExternalStore()
(since v18) -
useTransition()
(since v18)
-
ReactDOM.createPortal(children, container)
-
React.memo()
-
React.forwardRef()
-
React.lazy()
-
<Suspense>
-
<Offscreen>
(since v18)
If you find a bug, please file an issue on our issue tracker on GitHub.
Copyright © 2022 Shen Junru • MIT license.