0.7.1 • Published 3 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 FiberandReact Hooks. - Triggers original class component life circle.
- Triggers original effect hooks.
- Supports context updates.
- Supports multiple
keep-alive. - Supports
react-domv16.8+. - Supports
react-domv17. - Supports
react-domv18.
📦 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
rootcontainer element.<KeepAlive.Provider value={container}>- Must be the root container of
render(). - If not provided,
keep-alivewill 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
containerchanged inReactDOM.createPortal(children, container).- All saved sub tree state will be lost.
- Errors from
react-devtoolsafter<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.