react-next-keep-alive
Version:
Module for caching views in next.js
235 lines (229 loc) • 9.66 kB
JavaScript
import React, { cloneElement, useRef, useState, memo, useEffect, Fragment } from 'react';
var defaultEnabled = true;
var KeepAliveProvider = function KeepAliveProvider(props) {
var _componentData$type;
var children = props.children,
router = props.router;
var pageProps = children === null || children === void 0 ? void 0 : children.props;
var componentData = cloneElement(children);
var CurrentComponent = componentData === null || componentData === void 0 ? void 0 : componentData.type;
var keepAliveCache = useRef({});
var _useState = useState(),
forceUpdate = _useState[1];
var _ref = (componentData === null || componentData === void 0 ? void 0 : (_componentData$type = componentData.type) === null || _componentData$type === void 0 ? void 0 : _componentData$type.keepAlive) || {},
keepAliveName = _ref.name,
keepScrollEnabled = _ref.keepScrollEnabled,
applyNewProps = _ref.applyNewProps;
var name = typeof keepAliveName === 'function' ? keepAliveName({
props: pageProps,
router: router
}) : keepAliveName;
var isEnabled = function isEnabled() {
var _keepAliveCache$curre, _keepAliveCache$curre2;
return keepAliveCache === null || keepAliveCache === void 0 ? void 0 : (_keepAliveCache$curre = keepAliveCache.current) === null || _keepAliveCache$curre === void 0 ? void 0 : (_keepAliveCache$curre2 = _keepAliveCache$curre[name]) === null || _keepAliveCache$curre2 === void 0 ? void 0 : _keepAliveCache$curre2.enabled;
};
var isKeptAlive = !!name;
var keepScroll = !!keepScrollEnabled;
if (isKeptAlive && !keepAliveCache.current[name]) {
var Component = componentData === null || componentData === void 0 ? void 0 : componentData.type;
var MemoComponent = memo(Component);
keepAliveCache.current[name] = {
Component: MemoComponent,
pageProps: pageProps,
scrollPos: 0,
name: name,
enabled: defaultEnabled
};
}
var handleRouteChangeStart = function handleRouteChangeStart() {
var _keepAliveCache$curre3;
if (isKeptAlive && keepAliveCache !== null && keepAliveCache !== void 0 && (_keepAliveCache$curre3 = keepAliveCache.current) !== null && _keepAliveCache$curre3 !== void 0 && _keepAliveCache$curre3[name]) {
keepAliveCache.current[name].scrollPos = window.scrollY;
}
};
var handleRouteChangeComplete = function handleRouteChangeComplete() {
if (isKeptAlive && isEnabled() && keepScroll) {
var _keepAliveCache$curre4;
window.scrollTo(0, ((_keepAliveCache$curre4 = keepAliveCache.current[name]) === null || _keepAliveCache$curre4 === void 0 ? void 0 : _keepAliveCache$curre4.scrollPos) || 0);
setTimeout(function () {
var _keepAliveCache$curre5;
window.scrollTo(0, ((_keepAliveCache$curre5 = keepAliveCache.current[name]) === null || _keepAliveCache$curre5 === void 0 ? void 0 : _keepAliveCache$curre5.scrollPos) || 0);
}, 0);
}
};
var handleLoadFromCache = function handleLoadFromCache(event) {
var _ref2 = (event === null || event === void 0 ? void 0 : event.detail) || {},
controlsName = _ref2.name,
controlsEnabled = _ref2.enabled;
if (keepAliveCache.current[controlsName]) {
keepAliveCache.current[controlsName].enabled = controlsEnabled;
}
};
var handleDropCache = function handleDropCache(event) {
var _ref3 = (event === null || event === void 0 ? void 0 : event.detail) || {},
dropKeepAliveName = _ref3.name,
scrollToTop = _ref3.scrollToTop;
if (!dropKeepAliveName) {
keepAliveCache.current = {};
} else if (typeof dropKeepAliveName === 'string') {
var _keepAliveCache$curre6;
(_keepAliveCache$curre6 = keepAliveCache.current) === null || _keepAliveCache$curre6 === void 0 ? true : delete _keepAliveCache$curre6[dropKeepAliveName];
} else if (typeof dropKeepAliveName === 'function') {
var _cachesToRemove$filte;
var caches = dropKeepAliveName === null || dropKeepAliveName === void 0 ? void 0 : dropKeepAliveName(Object.keys(keepAliveCache.current));
var cachesToRemove = Array.isArray(caches) ? caches : [caches];
cachesToRemove === null || cachesToRemove === void 0 ? void 0 : (_cachesToRemove$filte = cachesToRemove.filter(function (exists) {
return exists;
})) === null || _cachesToRemove$filte === void 0 ? void 0 : _cachesToRemove$filte.forEach(function (cacheName) {
var _keepAliveCache$curre7;
return (_keepAliveCache$curre7 = keepAliveCache.current) === null || _keepAliveCache$curre7 === void 0 ? true : delete _keepAliveCache$curre7[cacheName];
});
}
if (scrollToTop && typeof window !== 'undefined') {
window.scrollTo(0, 0);
}
forceUpdate({});
};
useEffect(function () {
router.events.on('routeChangeStart', handleRouteChangeStart);
router.events.on('routeChangeComplete', handleRouteChangeComplete);
return function () {
router.events.off('routeChangeStart', handleRouteChangeStart);
router.events.off('routeChangeComplete', handleRouteChangeComplete);
};
}, [router.asPath]);
useEffect(function () {
if (isKeptAlive) {
window.dispatchEvent(new CustomEvent('onKeepAliveMount', {
detail: name
}));
return function () {
window.dispatchEvent(new CustomEvent('onKeepAliveUnmount', {
detail: name
}));
};
}
}, [CurrentComponent, pageProps]);
useEffect(function () {
window.addEventListener('keepAliveControls_LoadFromCache', handleLoadFromCache);
window.addEventListener('keepAliveControls_DropCache', handleDropCache);
return function () {
window.removeEventListener('keepAliveControls_LoadFromCache', handleLoadFromCache);
window.removeEventListener('keepAliveControls_DropCache', handleDropCache);
};
}, []);
var getCachedViewProps = function getCachedViewProps(cachedProps) {
if (applyNewProps === true) {
return pageProps;
}
if (typeof applyNewProps === 'function') {
return applyNewProps(cachedProps, pageProps);
}
return cachedProps;
};
var getKeepAliveEffect = function getKeepAliveEffect(isHidden) {
var useKeepAliveEffect = function useKeepAliveEffect(effect, deps) {
return useEffect(function () {
if (!isHidden) {
return effect();
}
}, deps);
};
return useKeepAliveEffect;
};
return React.createElement(Fragment, null, (!isKeptAlive || !isEnabled()) && children, React.createElement("div", {
style: {
display: isKeptAlive && isEnabled() ? 'block' : 'none'
},
id: "keep-alive-container",
"data-keepalivecontainer": true
}, Object.entries(keepAliveCache.current).map(function (_ref4) {
var cacheName = _ref4[0],
_ref4$ = _ref4[1],
Component = _ref4$.Component,
cachedProps = _ref4$.pageProps;
return React.createElement("div", {
key: cacheName,
style: {
display: name === cacheName ? 'block' : 'none'
},
"data-keepalive": cacheName,
"data-keepalive-hidden": name !== cacheName
}, React.createElement(Component, Object.assign({
isHiddenByKeepAlive: name !== cacheName,
useEffect: getKeepAliveEffect(name !== cacheName)
}, getCachedViewProps(cachedProps))));
})));
};
var defaultOpts = {
keepScrollEnabled: true,
applyNewProps: false
};
var withKeepAlive = function withKeepAlive(Component, name, opts) {
if (opts === void 0) {
opts = defaultOpts;
}
var KeepAlive = function KeepAlive(props) {
return React.createElement(Fragment, null, React.createElement(Component, Object.assign({}, props)));
};
if (Component.getInitialProps) {
KeepAlive.getInitialProps = Component.getInitialProps;
}
var _ref = opts || {},
keepScrollEnabled = _ref.keepScrollEnabled,
applyNewProps = _ref.applyNewProps;
KeepAlive.keepAlive = {
name: name,
keepScrollEnabled: keepScrollEnabled,
applyNewProps: applyNewProps
};
return KeepAlive;
};
var useKeepAliveMountEffect = function useKeepAliveMountEffect(name, effect) {
var handleMountedEvent = function handleMountedEvent(e) {
if ((e === null || e === void 0 ? void 0 : e.detail) === name && typeof effect === 'function') {
effect();
}
};
useEffect(function () {
window.addEventListener('onKeepAliveMount', handleMountedEvent);
return function () {
window.removeEventListener('onKeepAliveMount', handleMountedEvent);
};
}, []);
};
var useKeepAliveUnmountEffect = function useKeepAliveUnmountEffect(name, effect) {
var handleUnmountedEvent = function handleUnmountedEvent(e) {
if ((e === null || e === void 0 ? void 0 : e.detail) === name && typeof effect === 'function') {
effect();
}
};
useEffect(function () {
window.addEventListener('onKeepAliveUnmount', handleUnmountedEvent);
return function () {
window.removeEventListener('onKeepAliveUnmount', handleUnmountedEvent);
};
}, []);
};
function keepAliveLoadFromCache(name, enabled) {
if (typeof window !== 'undefined') {
window.dispatchEvent(new CustomEvent('keepAliveControls_LoadFromCache', {
detail: {
name: name,
enabled: enabled
}
}));
}
}
function keepAliveDropCache(name, scrollToTop) {
if (typeof window !== 'undefined') {
window.dispatchEvent(new CustomEvent('keepAliveControls_DropCache', {
detail: {
name: name,
scrollToTop: scrollToTop
}
}));
}
}
export { KeepAliveProvider, keepAliveDropCache, keepAliveLoadFromCache, useKeepAliveMountEffect, useKeepAliveUnmountEffect, withKeepAlive };
//# sourceMappingURL=index.modern.js.map