Skip to content

Commit 5d2593c

Browse files
committed
Add <Async.Pending> helper for not-yet-invoked deferFn.
1 parent c60113f commit 5d2593c

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ They don't have to be direct children of `<Async>` and you can use the same comp
205205

206206
### `<Async.Loading>`
207207

208-
Renders only while the promise is still pending.
208+
Renders only while the promise is loading.
209209

210210
#### Props
211211

@@ -262,6 +262,28 @@ Renders only when the promise is rejected.
262262
<Async.Rejected>{({ error }) => `Unexpected error: ${error.message}`}</Async.Rejected>
263263
```
264264

265+
### `<Async.Pending>`
266+
267+
Renders only while the deferred promise is still pending (not yet run).
268+
269+
#### Props
270+
271+
- `children` {Function|Node} Function which receives props object or React node
272+
273+
#### Examples
274+
275+
```js
276+
<Async deferFn={deferFn}>
277+
<Async.Pending>
278+
<p>This text is only rendered while `run` has not yet been invoked on `deferFn`.</p>
279+
</Async.Pending>
280+
</Async>
281+
```
282+
283+
```js
284+
<Async.Pending>{({ run }) => <button onClick={run}>Run</button>}</Async.Pending>
285+
```
286+
265287
## Acknowledgements
266288

267289
Many thanks to Andrey Popp for handing over ownership of `react-async` on npm.

src/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ export const createInstance = (defaultProps = {}) => {
110110
}
111111
}
112112

113+
/**
114+
* Renders only when deferred promise is pending (not yet run).
115+
*
116+
* @prop {Function|Node} children Function (passing error and props) or React node
117+
*/
118+
Async.Pending = ({ children }) => (
119+
<Consumer>
120+
{props => {
121+
if (props.isLoading || props.data || props.error) return null
122+
return typeof children === "function" ? children(props) : children || null
123+
}}
124+
</Consumer>
125+
)
126+
113127
/**
114128
* Renders only while loading.
115129
*

src/spec.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ test("Async.Resolved renders only after the promise is resolved", async () => {
235235
expect(queryByText("done")).toBeInTheDocument()
236236
})
237237

238-
test("Async.Loading renders only while the promise is pending", async () => {
238+
test("Async.Loading renders only while the promise is loading", async () => {
239239
const promiseFn = () => resolveTo("ok")
240240
const { getByText, queryByText } = render(
241241
<Async promiseFn={promiseFn}>
@@ -248,6 +248,23 @@ test("Async.Loading renders only while the promise is pending", async () => {
248248
expect(queryByText("loading")).toBeNull()
249249
})
250250

251+
test("Async.Pending renders only while the deferred promise is pending", async () => {
252+
const deferFn = () => resolveTo("ok")
253+
const { getByText, queryByText } = render(
254+
<Async deferFn={deferFn}>
255+
<Async.Pending>{({ run }) => <button onClick={run}>pending</button>}</Async.Pending>
256+
<Async.Loading>loading</Async.Loading>
257+
<Async.Resolved>done</Async.Resolved>
258+
</Async>
259+
)
260+
expect(queryByText("pending")).toBeInTheDocument()
261+
fireEvent.click(getByText("pending"))
262+
expect(queryByText("pending")).toBeNull()
263+
expect(queryByText("loading")).toBeInTheDocument()
264+
await waitForElement(() => getByText("done"))
265+
expect(queryByText("loading")).toBeNull()
266+
})
267+
251268
test("Async.Rejected renders only after the promise is rejected", async () => {
252269
const promiseFn = () => rejectTo("err")
253270
const { getByText, queryByText } = render(

0 commit comments

Comments
 (0)