diff --git a/__tests__/atomWithHash_spec.tsx b/__tests__/atomWithHash_spec.tsx index 443b5b4..1491fa9 100644 --- a/__tests__/atomWithHash_spec.tsx +++ b/__tests__/atomWithHash_spec.tsx @@ -1,4 +1,4 @@ -import React, { StrictMode, useMemo } from 'react'; +import React, { StrictMode, useEffect, useMemo, useState } from 'react'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { useAtom } from 'jotai/react'; @@ -186,6 +186,37 @@ describe('atomWithHash', () => { await user.type(screen.getByLabelText('b'), '1'); await waitFor(() => expect(paramBMockFn).toBeCalledTimes(4)); }); + + it('sets initial value from hash', async () => { + window.location.hash = '#count=2'; + const countAtom = atomWithHash('count', 0); + + const Counter = () => { + const [count] = useAtom(countAtom); + const [countWasZero, setCountWasZero] = useState(false); + + useEffect(() => { + if (count === 0) { + setCountWasZero(true); + } + }, [count]); + return ( + <> +
count: {count}
+
count was zero: {countWasZero.toString()}
+ + ); + }; + + const { findByText } = render( + + + , + ); + + await findByText('count: 2'); + await findByText('count was zero: false'); + }); }); describe('atomWithHash without window', () => { diff --git a/src/atomWithHash.ts b/src/atomWithHash.ts index 120b6e9..76b5d58 100644 --- a/src/atomWithHash.ts +++ b/src/atomWithHash.ts @@ -26,6 +26,7 @@ export function atomWithHash( }, ): WritableAtom], void> { const serialize = options?.serialize || JSON.stringify; + const deserialize = options?.deserialize || safeJSONParse(initialValue); const subscribe = options?.subscribe || @@ -51,15 +52,20 @@ export function atomWithHash( if (typeof setHashOption === 'function') { setHash = setHashOption; } - const strAtom = atom(null); + const isLocationAvailable = + typeof window !== 'undefined' && !!window.location; + + const strAtom = atom( + isLocationAvailable + ? new URLSearchParams(window.location.hash.slice(1)).get(key) + : null, + ); strAtom.onMount = (setAtom) => { - if (typeof window === 'undefined' || !window.location) { + if (!isLocationAvailable) { return undefined; } const callback = () => { - const searchParams = new URLSearchParams(window.location.hash.slice(1)); - const str = searchParams.get(key); - setAtom(str); + setAtom(new URLSearchParams(window.location.hash.slice(1)).get(key)); }; const unsubscribe = subscribe(callback); callback();