diff --git a/.changeset/brave-items-cover.md b/.changeset/brave-items-cover.md
new file mode 100644
index 0000000000..ad1de7aa9f
--- /dev/null
+++ b/.changeset/brave-items-cover.md
@@ -0,0 +1,5 @@
+---
+'@ice/runtime': patch
+---
+
+feat: support props for KeepAliveOutlet
diff --git a/examples/with-keep-alive/src/pages/layout.tsx b/examples/with-keep-alive/src/pages/layout.tsx
index c50545a199..cef958ddfc 100644
--- a/examples/with-keep-alive/src/pages/layout.tsx
+++ b/examples/with-keep-alive/src/pages/layout.tsx
@@ -4,7 +4,7 @@ export default function Layout() {
return (
Layout
-
+
);
}
diff --git a/packages/runtime/src/KeepAliveOutlet.tsx b/packages/runtime/src/KeepAliveOutlet.tsx
index d300e5b977..8c4a667f83 100644
--- a/packages/runtime/src/KeepAliveOutlet.tsx
+++ b/packages/runtime/src/KeepAliveOutlet.tsx
@@ -10,41 +10,54 @@ interface ActivityItem {
pathname: string;
}
-export default function KeepAliveOutlet() {
+interface OutletProps {
+ // The limitation number of outlets to keep alive.
+ limit?: number;
+ // When paths is configured, only the specified paths will be kept alive.
+ paths?: string[];
+}
+
+const OUTLET_LIMIT = 5;
+
+export default function KeepAliveOutlet(props: OutletProps) {
if (!Activity) {
throw new Error('`` now requires react experimental version. Please install it first.');
}
const [outlets, setOutlets] = useState([]);
const location = useLocation();
const outlet = useOutlet();
+ const outletLimit = props.limit || OUTLET_LIMIT;
+ const keepAlivePaths = props.paths;
+
// Save the first outlet for SSR hydration.
const outletRef = useRef({
key: location.key,
pathname: location.pathname,
outlet,
});
-
useEffect(() => {
// If outlets is empty, save the first outlet for SSR hydration,
// and should not call setOutlets to avoid re-render.
if (outlets.length !== 0 ||
outletRef.current?.pathname !== location.pathname) {
let currentOutlets = outletRef.current ? [outletRef.current] : outlets;
+ if (keepAlivePaths && keepAlivePaths.length > 0) {
+ currentOutlets = currentOutlets.filter(o => keepAlivePaths.includes(o.pathname));
+ }
const result = currentOutlets.some(o => o.pathname === location.pathname);
if (!result) {
setOutlets([
- // TODO: the max length of outlets should be configurable.
...currentOutlets,
{
key: location.key,
pathname: location.pathname,
outlet,
},
- ]);
+ ].slice(-outletLimit));
outletRef.current = null;
}
}
- }, [location.pathname, location.key, outlet, outlets]);
+ }, [location.pathname, location.key, outlet, outlets, outletLimit, keepAlivePaths]);
// Render initail outlet for SSR hydration.
const renderOutlets = outlets.length === 0 ? [outletRef.current] : outlets;