# `<Async>`
The `<Async>` component is meant for asynchronous rendering. E.g. loading page content.

=== "JSX"
	```jsx
	import { Async } from "rvx/async";

	// main.tsx:
	<Async source={() => import("./page")}>
		{page => <page.content />}
	</Async>

	// page.tsx:
	export function content() {
		return <h1>Hello World!</h1>;
	}
	```

=== "No Build"
	```jsx
	import { nestAsync } from "./rvx.async.js";

	// main.js:
	nestAsync(() => import("./page"), page => page.content())

	// page.js:
	export function content() {
		return e("h1").append("Hello World!");
	}
	```

The `rejected` and `pending` properties can be used for rendering content when the promise is rejected or pending:

=== "JSX"
	```jsx
	<Async
		source={() => import("./page")}
		pending={() => <>Loading...</>}
		rejected={error => <>Error: {error}</>}
	>
		{page => <page.content />}
	</Async>
	```

=== "No Build"
	```jsx
	nestAsync(
		() => import("./page"),
		page => page.content(),
		() => "Loading...",
		error => ["Error: ", error],
	)
	```

## Tracking Completion
To wait for async parts in a specific context to complete, you can use `AsyncContexts`:

=== "JSX"
	```jsx
	import { Provide } from "rvx";
	import { ASYNC, Async, AsyncContext } from "rvx/async";

	const ctx = new AsyncContext();

	<Provide context={ASYNC} value={ctx}>
		{() => <Async>...</Async>}
	</Provide>

	// Wait for all "<Async>" parts to complete and re-throw unhandled errors:
	await ctx.complete();

	// Or manually track an async task:
	ctx.track(fetch("something"));
	```

=== "No Build"
	```jsx
	import { ASYNC, Async, AsyncContext } from "./rvx.async.js";

	const ctx = new AsyncContext();

	ASYNC.provide(ctx, () => {
		return nestAsync(...);
	})

	// Wait for all "<Async>" parts to complete and re-throw unhandled errors:
	await ctx.complete();

	// Or manually track an async task:
	ctx.track(fetch("something"));
	```

### Revealing Content At Once
When there are multiple async parts in the same place, tracking can be used to hide an entire area and show it once all of the inner async parts have completed.

=== "JSX"
	```jsx
	import { $, Provide, movable } from "rvx";
	import { ASYNC, Async, AsyncContext } from "rvx/async";

	const innerCtx = new AsyncContext();
	const inner = movable(
		<Provide context={ASYNC} value={innerCtx}>
			{() => <>
				<Async>...</Async>
				<Async>...</Async>
				<Async>...</Async>
			</>}
		</Provide>
	);

	<Async source={innerCtx.complete()}>
		{() => inner.move()}
	</Async>
	```

=== "No Build"
	```jsx
	import { $, movable } from "./rvx.js";
	import { ASYNC, nestAsync, AsyncContext } from "./rvx.async.js";

	const innerCtx = new AsyncContext();
	const inner = movable(ASYNC.provide(innerCtx, () => [
		nestAsync(...),
		nestAsync(...),
		nestAsync(...),
	]));

	nestAsync(innerCtx.complete(), () => inner.move())
	```

## Dynamic Sources
The `<Show>` or `<Nest>` components can be used to replace the `source` property over time:

=== "JSX"
	```jsx
	<Show when={someSignal}>
		{source => <Async source={source}>...</Async>}
	</Show>
	```

=== "No Build"
	```jsx
	when(someSignal, source => nestAsync(source, ...))
	```

The example below fetches a file and aborts pending requests when the file name is changed early:

=== "JSX"
	```jsx
	const name = $("example.txt");

	<Nest watch={name}>
		{name => <Async source={fetch(name, { signal: useAbortSignal() }).then(r => r.text())}>
			{text => <pre>{text}</pre>}
		</Async>}
	</Nest>
	```

=== "No Build"
	```jsx
	const name = $("example.txt");

	nest(name, name => nestAsync(
		fetch(name, { signal: useAbortSignal() }).then(r => r.text()),
		text => e("pre").append(text)
	))
	```
