Hope to provide Keepalive component
Describe the bug
Hope to provide Keepalive component
Your Example Website or App
Hope to provide Keepalive component
Steps to Reproduce the Bug or Issue
Hope to provide Keepalive component
Expected behavior
Hope to provide Keepalive component
Screenshots or Videos
Hope to provide Keepalive component
Platform
- OS: [e.g. macOS, Windows, Linux]
- Browser: [e.g. Chrome, Safari, Firefox]
- Version: [e.g. 91.1] Hope to provide Keepalive component
Additional context
Hope to provide Keepalive component
I've been waiting for this feature for two years. You can check it out here: solid-router issue #204.
Currently, I'm using solid-keep-alive as an alternative.
Yes, in fact, you may not need an API like vue. This is a keep-alive function I implemented. It works well and meets all scenarios. Toggle is a substitute for Show.
export default function createKeepAlive() {
const owner = getOwner();
let cache:
| {
depose(): void;
el: JSX.Element;
}
| undefined = undefined;
function render(
el: () => JSX.Element,
active: Accessor<boolean> = () => true
) {
if (!cache) {
cache = createRoot((depose) => {
return {
el: <ActiveProvider value={active()} children={el()} />,
depose,
};
}, owner);
}
return cache.el;
}
onCleanup(() => {
cache && cache.depose();
});
return render;
}
export function Toggle<T>(props: ToggleProps<T>) {
let render: RenderType = (el) => el();
let renderFallback = render;
if (props.keepAlive !== false) {
render = createKeepAlive();
renderFallback = createKeepAlive();
}
const when = createMemo(() => Boolean(props.when));
return (
<Show
when={when()}
fallback={renderFallback(
() => props.fallback,
() => !when()
)}
>
{render(
() => props.children,
() => when()
)}
</Show>
);
}
export interface ToggleProps<T> {
when: T | undefined | null | false;
fallback?: JSX.Element;
children: JSX.Element;
keepAlive?: boolean;
}
type RenderType = (
el: () => JSX.Element,
active: Accessor<boolean>
) => JSX.Element;
You can also use object pool technology to cache loops, but these two are different concepts. Although vue is simple, it is actually very confusing. Each is a substitute for For.
import { createRootPool } from '@solid-primitives/rootless';
import { For, JSX } from 'solid-js';
import { useActiveMemo } from './Active';
export default function Each<T extends readonly any[]>(props: {
each: T | undefined | null | false;
fallback?: JSX.Element;
component: (props: { data: T[number]; active?: boolean }) => JSX.Element;
limit?: number;
}) {
const activeEach = useActiveMemo(() => props.each);
const pool = createRootPool<T[number], JSX.Element>(
(it, active) => {
const el = props.component({
get data() {
return it();
},
get active() {
return active();
},
});
return el;
},
{ limit: props.limit || 100 }
);
return (
<For each={activeEach()} fallback={props.fallback}>
{(it) => pool(it)}
</For>
);
}
@hex0xf Although your approach can achieve functionality, it lacks cache eviction strategies (which can easily lead to memory leaks) and some advanced features.