Skip to content
This repository was archived by the owner on May 20, 2026. It is now read-only.

Commit 1f4e0c8

Browse files
committed
really fix keepAlive component and add docs for isAlive
1 parent 90b4ac2 commit 1f4e0c8

2 files changed

Lines changed: 41 additions & 28 deletions

File tree

docs/primitives/KeepAlive.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,27 @@ const AppRoutes = () => {
3232

3333
In the example above, the `Browse` component's state will be preserved. When you navigate away and then back to a `/browse/...` URL, the page will render instantly from the cache, showing exactly what was there before.
3434

35+
### Suspending Effects for Cached Routes
36+
37+
When a route is cached and hidden (unmounted from view but kept in memory), its reactive SolidJS context remains active. This means any `createEffect` blocks that depend on global signals or stores will continue to run in the background.
38+
39+
To prevent background effects from running when the page is inactive, `KeepAliveRoute` injects an `isAlive` accessor into your component's props. You should use `isAlive()` to halt effects early.
40+
41+
```jsx
42+
import { createEffect } from 'solid-js';
43+
44+
const Browse = (props) => {
45+
createEffect(() => {
46+
// Return early to prevent the effect from running in the background when cached
47+
if (!props.isAlive()) return;
48+
49+
console.log('Page is active and visible!');
50+
});
51+
52+
return <view>...</view>;
53+
};
54+
```
55+
3556
### IMPORTANT PRELOAD TIPS
3657

3758
If using preload functions with props

src/primitives/KeepAlive.tsx

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -175,16 +175,19 @@ export const KeepAliveRoute = <S extends string>(
175175
const key = props.id || props.path;
176176
let savedFocusedElement: ElementNode | undefined;
177177

178-
let existing = keepAliveRouteElements.get(key);
179-
if (!existing) {
180-
const [isAlive, setIsAlive] = s.createSignal(true);
181-
keepAliveRouteElements.set(key, {
182-
id: key,
183-
isAlive,
184-
setIsAlive,
185-
} as any);
186-
existing = keepAliveRouteElements.get(key);
187-
}
178+
const getExisting = () => {
179+
let existing = keepAliveRouteElements.get(key);
180+
if (!existing) {
181+
const [isAlive, setIsAlive] = s.createSignal(true);
182+
existing = {
183+
id: key,
184+
isAlive,
185+
setIsAlive,
186+
} as any;
187+
keepAliveRouteElements.set(key, existing!);
188+
}
189+
return existing!;
190+
};
188191

189192
const onRemove = chainFunctions(props.onRemove, (elm: ElementNode) => {
190193
savedFocusedElement = activeElement() as ElementNode;
@@ -212,35 +215,24 @@ export const KeepAliveRoute = <S extends string>(
212215

213216
const preload = props.preload
214217
? (preloadProps: RoutePreloadFuncArgs) => {
215-
let existing = keepAliveRouteElements.get(key);
218+
let existing = getExisting();
216219

217220
if (
218-
existing &&
219221
existing.children &&
220222
(props.shouldDispose?.(key) ||
221223
(existing.children as unknown as ElementNode)?.destroyed)
222224
) {
223225
(existing.children as unknown as ElementNode).destroy();
224226
existing.dispose?.();
225227
keepAliveRouteElements.delete(key);
226-
existing = undefined;
228+
existing = getExisting();
227229
}
228230

229-
if (!existing || !existing.dispose) {
231+
if (!existing.dispose) {
230232
return s.createRoot((dispose) => {
231-
const [isAlive, setIsAlive] =
232-
existing?.isAlive && existing?.setIsAlive
233-
? [existing.isAlive, existing.setIsAlive]
234-
: s.createSignal(true);
235-
storeKeepAliveRoute({
236-
id: key,
237-
owner: s.getOwner(),
238-
dispose,
239-
children: null,
240-
isAlive,
241-
setIsAlive,
242-
});
243-
return props.preload!({ ...preloadProps, isAlive });
233+
existing.owner = s.getOwner();
234+
existing.dispose = dispose;
235+
return props.preload!({ ...preloadProps, isAlive: existing.isAlive! });
244236
});
245237
} else if (existing.children) {
246238
(existing.children as unknown as ElementNode)?.setFocus();
@@ -259,7 +251,7 @@ export const KeepAliveRoute = <S extends string>(
259251
{...props}
260252
preload={preload}
261253
component={(childProps) => {
262-
const existing = keepAliveRouteElements.get(key)!;
254+
const existing = getExisting();
263255
return (
264256
<KeepAliveRouteInternal
265257
id={key}

0 commit comments

Comments
 (0)