From d6b3e0c611d4528313818191616202a6d29779b7 Mon Sep 17 00:00:00 2001 From: freddie Date: Sat, 28 Oct 2023 23:32:47 +0100 Subject: [PATCH] fix: useActionData now ignores Response --- CHANGELOG.md | 6 +++++ README.md | 5 ++-- package.json | 2 +- src/__tests__/action.typetest.ts | 39 ++++++++++++++++++++++++++++++++ src/__tests__/loader.typetest.ts | 4 ++-- src/action.ts | 4 +++- 6 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 src/__tests__/action.typetest.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index c1d56df..4c0c4e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # react-router-typesafe +## 1.3.4 + +### Patch Changes + +- `useActionData` now ignores Response objects as expected + ## 1.3.3 ### Patch Changes diff --git a/README.md b/README.md index 5d848cf..cafbcd6 100644 --- a/README.md +++ b/README.md @@ -60,11 +60,12 @@ Feel free to improve the code and submit a pull request. If you're not sure abou | Status | Utility | Before | After | | ------ | -------------------- | ---------- | ------------------------------------------------------------ | | ✅ | `defer` | `Response` | Generic matching the first argument | +| | `json` | `Response` | Serialized data passed in | | ✅ | `useLoaderData` | `unknown` | Generic function with the type of the loader function passed | | ✅ | `useActionData` | `unknown` | Generic function with the type of the action function passed | | ✅ | `useRouteLoaderData` | `unknown` | Generic function with the type of the loader function passed | -| NEW | `makeLoader` | `unknown` | Wrapper around `satisfies` for ergonomics | -| NEW | `makeAction` | `unknown` | Wrapper around `satisfies` for ergonomics | +| NEW | `makeLoader` | | Wrapper around `satisfies` for ergonomics | +| NEW | `makeAction` | | Wrapper around `satisfies` for ergonomics | ## Patched components diff --git a/package.json b/package.json index 9c243a8..80535e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-router-typesafe", - "version": "1.3.3", + "version": "1.3.4", "repository": { "type": "git", "url": "https://github.com/stargaze-co/react-router-typesafe.git" diff --git a/src/__tests__/action.typetest.ts b/src/__tests__/action.typetest.ts new file mode 100644 index 0000000..7f56c45 --- /dev/null +++ b/src/__tests__/action.typetest.ts @@ -0,0 +1,39 @@ +import { test } from 'bun:test'; +import { ActionFunction, LoaderFunction, redirect } from 'react-router-dom'; +import { useActionData } from '..'; +/** TODO: wait for feedback on issue about act-compat importing deprecated "react-dom/test-utils" */ +import { renderHook } from '@testing-library/react'; +import { expectTypeOf } from 'expect-type'; + +test('works with non-promises', () => { + const testAction = (() => { + return { foo: 'bar' }; + }) satisfies ActionFunction; + + const { result } = renderHook(useActionData); + expectTypeOf(result.current).toEqualTypeOf<{ foo: string } | undefined>(); +}); + +test('works with promises', () => { + const testAction = (async () => { + return { foo: 'bar' }; + }) satisfies ActionFunction; + + const { result } = renderHook(useActionData); + expectTypeOf(result.current).toEqualTypeOf<{ foo: string } | undefined>(); +}); + +test('ignores redirects or responses', () => { + const testAction = (() => { + if (Math.random() > 0.5) { + return redirect('/foo'); + } + if (Math.random() > 0.5) { + return new Response(null, {}); + } + return { foo: 'bar' }; + }) satisfies ActionFunction; + + const { result } = renderHook(useActionData); + expectTypeOf(result.current).toEqualTypeOf<{ foo: string } | undefined>(); +}); diff --git a/src/__tests__/loader.typetest.ts b/src/__tests__/loader.typetest.ts index 92a2f2f..4cd8869 100644 --- a/src/__tests__/loader.typetest.ts +++ b/src/__tests__/loader.typetest.ts @@ -1,5 +1,5 @@ import { test } from 'bun:test'; -import { LoaderFunction, redirect } from 'react-router-dom'; +import { LoaderFunction, json, redirect } from 'react-router-dom'; import { useLoaderData } from '..'; /** TODO: wait for feedback on issue about act-compat importing deprecated "react-dom/test-utils" */ import { renderHook } from '@testing-library/react'; @@ -57,7 +57,7 @@ test('works with redirects', () => { expectTypeOf(result.current).toEqualTypeOf<{ foo: string }>(); }); -test.skip('routeLoaderData works the same way as useLoaderData', () => { +test('routeLoaderData works the same way as useLoaderData', () => { const testLoader = (() => { if (Math.random() > 0.5) { return redirect('/foo'); diff --git a/src/action.ts b/src/action.ts index c516d66..cd20ae0 100644 --- a/src/action.ts +++ b/src/action.ts @@ -1,6 +1,8 @@ import { ActionFunction, useActionData as rrUseActionData } from 'react-router-dom'; -export type ActionData = Awaited> | undefined; +export type ActionData = Awaited> extends Response | infer D + ? D | undefined + : never; /** Returns the action data for the nearest ancestor Route action * @example