0.7.1 • Published 2 years ago
react-fiber-keep-alive v0.7.1
Keep-Alive for React DOM
<KeepAlive>
is a component that maintains component state and avoids repeated re-rendering.
✨ Features
- 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.
📦 Installation
npm install --save react-fiber-keep-alive
🔨 Usage
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);
📝 API
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> ); };
💡 Tips
- 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)
🏁 Tested
Examples
React v16.8+ / v17 / v18
render(children, container)
hydrate(children, container)
React v18 (concurrent mode)
createRoot(container).render(children)
hydrateRoot(container, children)
Class Component
Component.getDerivedStateFromProps()
Component.getDerivedStateFromError()
instance.componentDidMount()
instance.getSnapshotBeforeUpdate()
instance.componentDidUpdate()
instance.componentWillUnmount()
instance.render()
Function Component
useContext()
useCallback()
useEffect()
useImperativeHandle()
useLayoutEffect()
useMemo()
useRef()
useState()
useDebugValue()
useDeferredValue()
(since v18)useId()
(since v18)useInsertionEffect()
(since v18)useSyncExternalStore()
(since v18)useTransition()
(since v18)
Other
ReactDOM.createPortal(children, container)
React.memo()
React.forwardRef()
React.lazy()
<Suspense>
<Offscreen>
(since v18)
🐛 Issues
If you find a bug, please file an issue on our issue tracker on GitHub.
📄 License
Copyright © 2022 Shen Junru • MIT license.