Skip to content

Commit 169c75a

Browse files
committed
better typings for run, add example
1 parent 6f8ab2a commit 169c75a

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
@@ -9,6 +9,7 @@ import Async, {
99
} from "react-async"
1010
import DevTools from "react-async-devtools"
1111
import "./App.css"
12+
import { FetchHookExample } from "./FetchHookExample";
1213

1314
const loadFirstName: PromiseFn<string> = ({ userId }) =>
1415
fetch(`https://reqres.in/api/users/${userId}`)
@@ -50,6 +51,7 @@ class App extends Component {
5051
<CustomAsync.Resolved>{data => <>{data}</>}</CustomAsync.Resolved>
5152
</CustomAsync>
5253
<UseAsync />
54+
<FetchHookExample />
5355
</header>
5456
</div>
5557
)
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
@@ -22,7 +22,7 @@ export type DeferFn<T> = (
2222

2323
interface AbstractAction {
2424
type: string
25-
meta: { counter: number; [meta: string]: any }
25+
meta: { counter: number;[meta: string]: any }
2626
}
2727
export type Start = AbstractAction & { type: "start"; payload: () => Promise<void> }
2828
export type Cancel = AbstractAction & { type: "cancel" }
@@ -130,7 +130,7 @@ export type AsyncRejected<T> = AbstractState<T> & {
130130
}
131131
export type AsyncState<T> = AsyncInitial<T> | AsyncPending<T> | AsyncFulfilled<T> | AsyncRejected<T>
132132

133-
export class Async<T> extends React.Component<AsyncProps<T>, AsyncState<T>> {}
133+
export class Async<T> extends React.Component<AsyncProps<T>, AsyncState<T>> { }
134134

135135
export namespace Async {
136136
export function Initial<T>(props: {
@@ -225,6 +225,17 @@ export function useFetch<T>(
225225
input: RequestInfo,
226226
init?: RequestInit,
227227
options?: FetchOptions<T>
228-
): AsyncState<T>
228+
): AsyncInitialWithout<'run', T> & FetchRun<T>;
229+
230+
// unfortunately, we cannot just omit K from AsyncInitial as that would unbox the Discriminated Union
231+
type AsyncInitialWithout<K extends keyof AsyncInitial<T>, T> = (Omit<AsyncInitial<T>, K> | Omit<AsyncPending<T>, K> | Omit<AsyncFulfilled<T>, K> | Omit<AsyncRejected<T>, K>);
232+
233+
type FetchRun<T> = {
234+
run(overrideInit: Partial<RequestInit>): Promise<T>
235+
run(overrideInit: (init: RequestInit) => RequestInit): Promise<T>
236+
run(ignoredEvent: React.SyntheticEvent): Promise<T>;
237+
run(ignoredEvent: Event): Promise<T>;
238+
run(): Promise<T>;
239+
};
229240

230241
export default Async

0 commit comments

Comments
 (0)