(
defaultOptions: AsyncProps<T> = {},
displayName = "Async"
)
| 69 | * A unique instance also uses its own React context for better nesting capability. |
| 70 | */ |
| 71 | export function createInstance<T>( |
| 72 | defaultOptions: AsyncProps<T> = {}, |
| 73 | displayName = "Async" |
| 74 | ): AsyncConstructor<T> { |
| 75 | const { Consumer: UnguardedConsumer, Provider } = React.createContext<AsyncState<T> | undefined>( |
| 76 | undefined |
| 77 | ) |
| 78 | function Consumer({ children }: { children: (value: AsyncState<T>) => React.ReactNode }) { |
| 79 | return ( |
| 80 | <UnguardedConsumer> |
| 81 | {value => { |
| 82 | if (!value) { |
| 83 | throw new Error( |
| 84 | "this component should only be used within an associated <Async> component!" |
| 85 | ) |
| 86 | } |
| 87 | return children(value) |
| 88 | }} |
| 89 | </UnguardedConsumer> |
| 90 | ) |
| 91 | } |
| 92 | |
| 93 | type Props = AsyncProps<T> |
| 94 | type State = AsyncState<T> |
| 95 | type Constructor = AsyncConstructor<T> |
| 96 | |
| 97 | class Async extends React.Component<Props, State> { |
| 98 | private mounted = false |
| 99 | private counter = 0 |
| 100 | private args: any[] = [] |
| 101 | private promise?: Promise<T> = neverSettle |
| 102 | private abortController: AbortController = new MockAbortController() |
| 103 | private debugLabel?: string |
| 104 | private dispatch: (action: AsyncAction<T>, ...args: any[]) => void |
| 105 | |
| 106 | constructor(props: Props) { |
| 107 | super(props) |
| 108 | |
| 109 | this.start = this.start.bind(this) |
| 110 | this.load = this.load.bind(this) |
| 111 | this.run = this.run.bind(this) |
| 112 | this.cancel = this.cancel.bind(this) |
| 113 | this.onResolve = this.onResolve.bind(this) |
| 114 | this.onReject = this.onReject.bind(this) |
| 115 | this.setData = this.setData.bind(this) |
| 116 | this.setError = this.setError.bind(this) |
| 117 | |
| 118 | const promise = props.promise |
| 119 | const promiseFn = props.promiseFn || defaultOptions.promiseFn |
| 120 | const initialValue = props.initialValue || defaultOptions.initialValue |
| 121 | |
| 122 | this.state = { |
| 123 | ...init<T>({ initialValue, promise, promiseFn }), |
| 124 | cancel: this.cancel, |
| 125 | run: this.run, |
| 126 | reload: () => { |
| 127 | this.load() |
| 128 | this.run(...this.args) |
no outgoing calls
no test coverage detected