Skip to content

Commit e804328

Browse files
committed
refactor: clearer initial state
1 parent 0664b35 commit e804328

File tree

5 files changed

+42
-22
lines changed

5 files changed

+42
-22
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { ReactNode, useEffect, useState } from 'react';
2+
3+
export function DelayedRender({ children }: { children: ReactNode }) {
4+
const [isReady, setIsReady] = useState(false);
5+
6+
useEffect(() => {
7+
const timeout = setTimeout(() => {
8+
setIsReady(true);
9+
}, 1000);
10+
11+
return () => {
12+
clearTimeout(timeout);
13+
};
14+
}, []);
15+
16+
return isReady ? <>{children}</> : null;
17+
}

apps/docs/components/examples/InitialValue.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Callout } from 'nextra/components';
21
import { useUrlState } from 'react-use-url-state';
32
import { z } from 'zod';
43

@@ -18,7 +17,7 @@ export function InitialValue({
1817
from: z.coerce.date().optional(),
1918
}),
2019
{
21-
search: 'init',
20+
search: applyInitialValue ? 'init-apply' : 'init-not-apply',
2221
limit: 1,
2322
from: new Date('1000-01-01'),
2423
},

apps/docs/pages/examples/initial-value-applied.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Callout } from 'nextra/components';
2+
import { DelayedRender } from '../../components/DelayedRender';
23
import { InitialValue } from '../../components/examples/InitialValue';
34

45
# Initial value (applied to URL)
@@ -41,4 +42,7 @@ return (
4142
);
4243
```
4344

44-
<InitialValue applyInitialValue={true} />
45+
<DelayedRender>
46+
{/* Fix for a weird on page load "rollback of URL params to empty. Not happening if another page is open first */}
47+
<InitialValue applyInitialValue={true} />
48+
</DelayedRender>

packages/core/src/index.ts

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,6 @@ export function useUrlState<T extends DefaultSchema>(
4646
() => new GenericRouter(update, {}),
4747
);
4848

49-
useEffect(() => {
50-
router.init();
51-
return () => {
52-
router.destroy();
53-
};
54-
}, [router]);
55-
5649
return useUrlStateWithRouter(schema, initialValue || null, {
5750
applyInitialValue: false,
5851
...options,
@@ -66,7 +59,6 @@ export function useUrlStateWithRouter<T extends DefaultSchema>(
6659
options: UrlStateOptions & { router: UrlStateRouter },
6760
): UrlState<T> & UrlStateMethods<T> {
6861
const schemaRef = useRef(schema);
69-
7062
const cachedInitialValue = useShallowEqualValue(initialValue);
7163

7264
const [state, setState] = useState<UrlState<T>>({
@@ -76,6 +68,7 @@ export function useUrlStateWithRouter<T extends DefaultSchema>(
7668
isReady: false,
7769
});
7870

71+
// needed it order to make handler functions stable
7972
const stateRef = useRef(state);
8073
stateRef.current = state;
8174

@@ -86,7 +79,7 @@ export function useUrlStateWithRouter<T extends DefaultSchema>(
8679
const validationResult = schemaRef.current.safeParse(object);
8780

8881
const result = validationResult.success
89-
? { success: true, data: validationResult.data, error: null }
82+
? { success: true, data: validationResult.data ?? null, error: null }
9083
: { success: false, data: object, error: validationResult.error };
9184

9285
setState({
@@ -105,28 +98,34 @@ export function useUrlStateWithRouter<T extends DefaultSchema>(
10598
};
10699
}, [recalculateState]);
107100

101+
useEffect(() => {
102+
if (state.isReady) {
103+
options.router.init();
104+
}
105+
return () => {
106+
options.router.destroy();
107+
};
108+
}, [options.router, state.isReady]);
109+
108110
const push = usePush(options.router);
109111

110112
const handlers = useHandlers<T>(push, stateRef);
111113

112114
// set the state from initial url
113115
useEffect(() => {
114-
if (!cachedInitialValue) {
115-
update(window.location.search);
116-
} else if (
117-
state.isReady &&
118-
options.applyInitialValue &&
119-
cachedInitialValue &&
120-
searchIsEmpty(window.location.search)
121-
) {
122-
handlers.setState({ ...state.data, ...cachedInitialValue });
116+
const searchString = window.location.search;
117+
118+
if (!searchIsEmpty(searchString)) {
119+
update(searchString);
120+
} else if (cachedInitialValue && options.applyInitialValue) {
121+
handlers.setState(cachedInitialValue);
123122
} else {
124123
setState((st) => ({
125124
...st,
126125
isReady: true,
127126
}));
128127
}
129-
}, [state.isReady, cachedInitialValue, options.applyInitialValue]);
128+
}, [cachedInitialValue, options.applyInitialValue]);
130129

131130
return { ...state, ...handlers };
132131
}

packages/core/src/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ function shallowEqual<T>(a: T, b: T) {
7171
export function useShallowEqualValue<T>(value: T) {
7272
const ref = useRef(value);
7373
if (!shallowEqual(value, ref.current)) {
74+
console.log('not equal');
7475
ref.current = value;
7576
}
7677
return ref.current;

0 commit comments

Comments
 (0)