Skip to content

Commit 0e5ccae

Browse files
committed
better typings for run, add example
1 parent 1f22240 commit 0e5ccae

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

examples/with-typescript/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component } from "react"
22
import Async, { createInstance } from "react-async"
33
import DevTools from "react-async-devtools"
44
import "./App.css"
5+
import { FetchHookExample } from "./FetchHookExample";
56

67
const promiseFn = () => Promise.resolve("baz")
78
const CustomAsync = createInstance({ promiseFn })
@@ -19,6 +20,7 @@ class App extends Component {
1920
<CustomAsync>
2021
<CustomAsync.Resolved>{data => <>{data}</>}</CustomAsync.Resolved>
2122
</CustomAsync>
23+
<FetchHookExample />
2224
</header>
2325
</div>
2426
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import * as React from 'react';
2+
import { useFetch } from 'react-async/src';
3+
4+
export function FetchHookExample() {
5+
const result = useFetch<{ token: string }>('https://reqres.in/api/login', { method: 'POST' });
6+
const { run } = result;
7+
8+
return (<>
9+
<button onClick={run}>just run it without login data</button>
10+
<button onClick={() => run(init => ({
11+
...init, body: JSON.stringify({
12+
"email": "[email protected]",
13+
"password": "cityslicka"
14+
})
15+
}))}>run it with valid login data (init callback)</button>
16+
17+
<button onClick={() => run(({
18+
body: JSON.stringify({
19+
"email": "[email protected]",
20+
"password": "cityslicka"
21+
})
22+
}))}>run it with valid login data (init object)</button>
23+
<br />
24+
Status:<br />
25+
{result.isInitial && "initial"}
26+
{result.isLoading && "loading"}
27+
{result.isResolved && result.data.token}
28+
</>)
29+
}

packages/react-async/src/index.d.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export type DeferFn<T> = (args: any[], props: object, controller: AbortControlle
66

77
interface AbstractAction {
88
type: string
9-
meta: { counter: number; [meta: string]: any }
9+
meta: { counter: number;[meta: string]: any }
1010
}
1111
export type Start = AbstractAction & { type: "start"; payload: () => Promise<void> }
1212
export type Cancel = AbstractAction & { type: "cancel" }
@@ -114,7 +114,7 @@ export type AsyncRejected<T> = AbstractState<T> & {
114114
}
115115
export type AsyncState<T> = AsyncInitial<T> | AsyncPending<T> | AsyncFulfilled<T> | AsyncRejected<T>
116116

117-
export class Async<T> extends Component<AsyncProps<T>, AsyncState<T>> {}
117+
export class Async<T> extends Component<AsyncProps<T>, AsyncState<T>> { }
118118

119119
export namespace Async {
120120
export function Initial<T>(props: { children?: AsyncChildren<T>; persist?: boolean }): JSX.Element
@@ -161,6 +161,17 @@ export function useFetch<T>(
161161
input: RequestInfo,
162162
init?: RequestInit,
163163
options?: FetchOptions<T>
164-
): AsyncState<T>
164+
): AsyncInitialWithout<'run', T> & FetchRun<T>;
165+
166+
// unfortunately, we cannot just omit K from AsyncInitial as that would unbox the Discriminated Union
167+
type AsyncInitialWithout<K extends keyof AsyncInitial<T>, T> = (Omit<AsyncInitial<T>, K> | Omit<AsyncPending<T>, K> | Omit<AsyncFulfilled<T>, K> | Omit<AsyncRejected<T>, K>);
168+
169+
type FetchRun<T> = {
170+
run(overrideInit: Partial<RequestInit>): Promise<T>
171+
run(overrideInit: (init: RequestInit) => RequestInit): Promise<T>
172+
run(ignoredEvent: React.SyntheticEvent): Promise<T>;
173+
run(ignoredEvent: Event): Promise<T>;
174+
run(): Promise<T>;
175+
};
165176

166177
export default Async

0 commit comments

Comments
 (0)