|
1 | | -import React, { ReactElement, ReactNode } from 'react' |
| 1 | +import { ReactElement, ReactNode } from 'react' |
2 | 2 | import { isFunction } from '../util' |
3 | 3 |
|
4 | 4 | type LoadingFunction = () => ReactNode |
5 | 5 | type SuccessFunction<Data> = (data: Data) => ReactNode |
6 | 6 | type ErrorFunction<Error> = (error: NonNullable<Error>) => ReactNode |
7 | 7 |
|
8 | 8 | type Props<Data, Error> = { |
9 | | - data?: Data |
10 | | - error?: Error |
11 | | - isLoading: boolean |
| 9 | + /** |
| 10 | + * The async data to show. |
| 11 | + * Note that `error` and `isLoading` take precedence over data. |
| 12 | + */ |
| 13 | + data: Data | undefined |
| 14 | + /** |
| 15 | + * Set an error to show the error state. |
| 16 | + * Note that `isLoading` takes precedence over error. |
| 17 | + */ |
| 18 | + error: Error | undefined |
| 19 | + /** |
| 20 | + * Set to a boolean value to explicitly control loading state. |
| 21 | + * If undefined, loading state is shown when there is no data (null | undefined) and no error (null | undefined). |
| 22 | + */ |
| 23 | + isLoading: boolean | undefined |
12 | 24 | renderLoading?: ReactNode | LoadingFunction |
13 | 25 | renderError?: ReactNode | ErrorFunction<Error> |
14 | 26 | } & ( |
@@ -36,15 +48,18 @@ const AsyncView = <Data, Error>( |
36 | 48 | allowMissingData = false, |
37 | 49 | } = props |
38 | 50 |
|
39 | | - if (isLoading) { |
| 51 | + const isError = error !== null && error !== undefined |
| 52 | + const hasData = data !== null && data !== undefined |
| 53 | + |
| 54 | + if (isLoading || (isLoading === undefined && !hasData && !isError)) { |
40 | 55 | return <>{isFunction(renderLoading) ? renderLoading() : renderLoading}</> |
41 | 56 | } |
42 | 57 |
|
43 | | - if (error !== null && error !== undefined) { |
| 58 | + if (isError) { |
44 | 59 | return <>{isFunction(renderError) ? renderError(error) : renderError}</> |
45 | 60 | } |
46 | 61 |
|
47 | | - if ((data === undefined || data === null) && !allowMissingData) { |
| 62 | + if (!hasData && !allowMissingData) { |
48 | 63 | throw new Error( |
49 | 64 | 'Data passed into AsyncView was null or undefined. Use allowMissingData=true if this is intended.', |
50 | 65 | ) |
|
0 commit comments