Skip to content

Commit 72ae532

Browse files
committed
router tweaks
1 parent 660ab8f commit 72ae532

3 files changed

Lines changed: 26 additions & 52 deletions

File tree

src/data/createAsync.ts

Lines changed: 9 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
1-
/**
2-
* Wrapper around Solid 2.0 async createMemo.
3-
*
4-
* In Solid 2.0, createMemo can return a Promise and the reactive graph
5-
* handles suspension automatically. `createAsync` is therefore a thin
6-
* wrapper that feeds the user-supplied async function into createMemo
7-
* and exposes a `.latest` convenience property.
8-
*/
9-
import { createMemo, latest as solidLatest } from "solid-js";
10-
import { isServer } from "@solidjs/web";
11-
12-
export type AccessorWithLatest<T> = {
13-
(): T;
14-
latest: T;
15-
};
1+
import { createMemo } from "solid-js";
162

173
/** Options for store reconciliation in Solid 2.0 */
184
export interface ReconcileOptions {
@@ -27,35 +13,24 @@ export function createAsync<T>(
2713
initialValue: T;
2814
deferStream?: boolean;
2915
}
30-
): AccessorWithLatest<T>;
16+
): () => T;
3117
export function createAsync<T>(
3218
fn: (prev: T | undefined) => Promise<T>,
3319
options?: {
3420
name?: string;
3521
initialValue?: T;
3622
deferStream?: boolean;
3723
}
38-
): AccessorWithLatest<T | undefined>;
24+
): () => T | undefined;
3925
export function createAsync<T>(
4026
fn: (prev: T | undefined) => Promise<T>,
4127
options?: {
4228
name?: string;
4329
initialValue?: T;
4430
deferStream?: boolean;
4531
}
46-
): AccessorWithLatest<T | undefined> {
47-
// In Solid 2.0, createMemo natively handles Promises.
48-
// The memo suspends until the promise resolves; <Loading> catches it.
49-
const memo = createMemo(() => fn(undefined));
50-
51-
const resultAccessor: AccessorWithLatest<T> = (() => memo()) as any;
52-
Object.defineProperty(resultAccessor, "latest", {
53-
get() {
54-
return solidLatest(memo);
55-
}
56-
});
57-
58-
return resultAccessor;
32+
): () => T | undefined {
33+
return createMemo(() => fn(undefined)) as () => T | undefined;
5934
}
6035

6136
export function createAsyncStore<T>(
@@ -66,7 +41,7 @@ export function createAsyncStore<T>(
6641
deferStream?: boolean;
6742
reconcile?: ReconcileOptions;
6843
}
69-
): AccessorWithLatest<T>;
44+
): () => T;
7045
export function createAsyncStore<T>(
7146
fn: (prev: T | undefined) => Promise<T>,
7247
options?: {
@@ -75,7 +50,7 @@ export function createAsyncStore<T>(
7550
deferStream?: boolean;
7651
reconcile?: ReconcileOptions;
7752
}
78-
): AccessorWithLatest<T | undefined>;
53+
): () => T | undefined;
7954
export function createAsyncStore<T>(
8055
fn: (prev: T | undefined) => Promise<T>,
8156
options: {
@@ -84,17 +59,6 @@ export function createAsyncStore<T>(
8459
deferStream?: boolean;
8560
reconcile?: ReconcileOptions;
8661
} = {}
87-
): AccessorWithLatest<T | undefined> {
88-
// Derived store form: createStore(fn) in Solid 2.0 creates a projection.
89-
// For now, fall back to the same async memo approach.
90-
const memo = createMemo(() => fn(undefined));
91-
92-
const resultAccessor: AccessorWithLatest<T> = (() => memo()) as any;
93-
Object.defineProperty(resultAccessor, "latest", {
94-
get() {
95-
return solidLatest(memo);
96-
}
97-
});
98-
99-
return resultAccessor;
62+
): () => T | undefined {
63+
return createMemo(() => fn(undefined)) as () => T | undefined;
10064
}

src/data/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export { createAsync, createAsyncStore, type AccessorWithLatest } from "./createAsync.js";
1+
export { createAsync, createAsyncStore } from "./createAsync.js";
22
export { action, useSubmission, useSubmissions, useAction, type Action } from "./action.js";
33
export { query, revalidate, cache, type CachedFunction } from "./query.js";
44
export { redirect, reload, json } from "./response.js";

src/routing.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,24 @@ const MAX_REDIRECTS = 100;
5151
export const RouterContextObj = createContext<RouterContext>();
5252
export const RouteContextObj = createContext<RouteContext>();
5353

54-
export const useRouter = () =>
55-
invariant(
56-
useContext(RouterContextObj),
57-
"<A> and 'use' router primitives can be only used inside a Route."
58-
);
54+
export const useRouter = () => {
55+
const router = useContext(RouterContextObj);
56+
return invariant(router, "<A> and 'use' router primitives can be only used inside a Route.");
57+
};
5958

6059
let TempRoute: RouteContext | undefined;
61-
export const useRoute = () => TempRoute || useContext(RouteContextObj) || useRouter().base;
60+
export const useRoute = () => {
61+
if (TempRoute) return TempRoute;
62+
63+
let route: RouteContext | undefined;
64+
try {
65+
route = useContext(RouteContextObj);
66+
} catch (e) {
67+
// In newer Solid versions, useContext throws if no provider and no default value
68+
}
69+
70+
return route || useRouter().base;
71+
};
6272

6373
export const useResolvedPath = (path: () => string) => {
6474
const route = useRoute();

0 commit comments

Comments
 (0)