React DOM
<KeepAlive>
is a component that maintains component state and avoids repeated re-rendering.
React Fiber
and React Hooks
.keep-alive
.react-dom
v16.8+.react-dom
v17.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}>
render()
.keep-alive
will be disabled.Wrap your component with <KeepAlive>
<KeepAlive name="unique-key">
<YourComponent />
</KeepAlive>
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>
);
};
<KeepAlive>
under the <React.StrictMode>
.<KeepAlive>
handled by top level <KeepAlive>
.container
changed in ReactDOM.createPortal(children, container)
.
react-devtools
after <KeepAlive>
remounted.
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.