UNPKG

react-async-iterators

Version:

The magic of JavaScript async iterators in React ⛓️ 🧬 🔃

119 lines 4.51 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Iterate = Iterate; const index_js_1 = require("../useAsyncIter/index.js"); /** * The `<Iterate>` component (also exported as `<It>`) is used to format and render an async * iterable (or a plain non-iterable value) directly onto a piece of UI. * * Essentially, can be seen as a {@link useAsyncIter `useAsyncIter`} hook in a component form, * conveniently. * * _Illustration:_ * * ```tsx * import { It } from 'react-async-iterators'; * * function SelfUpdatingTodoList(props) { * return ( * <div> * <h2>My TODOs</h2> * * <div> * Last TODO was completed at: <It>{props.lastCompletedTodoDate}</It> * </div> * * <ul> * <It value={props.todosAsyncIter}> * {({ value: todos }) => * todos?.map(todo => * <li key={todo.id}>{todo.text}</li> * ) * } * </It> * </ul> * </div> * ); * } * ``` * * `<Iterate>` may be preferable over the {@link useAsyncIter `useAsyncIter`} counterpart typically as * the UI area it re-renders within a component tree can be expressly confined to the necessary * minimum, saving any other unrelated elements from re-evaluation - while on the other hand * {@link useAsyncIter `useAsyncIter`} being a hook it has to re-render an entire * component's output for every new value. * * Given an async iterable as the `value` prop, this component will iterate it and render every new * value that becomes available together with any possible completion or error it may run into. * If `value` is a plain (non async iterable) value, it will simply be rendered as-is. * * Whenever given `value` is changed from the previous one seen, `<Iterate>` will close the previous * if it was async iterable before proceeding to iterate the new `value`. Care should be taken to * avoid passing a constantly recreated iterable object across re-renders, e.g; by declaring it outside * the component body or by controlling __when__ it should be recreated with React's * [`useMemo`](https://react.dev/reference/react/useMemo). `<Iterate>` will automatically close its iterated iterable as soon as it gets unmounted. * * --- * * @template TVal The type of values yielded by the passed iterable or otherwise type of the passed plain value itself. * @template TInitialVal The type of the initial value, defaults to `undefined`. * * @param props Props for `<Iterate>`. See {@link IterateProps `IterateProps`}. * * @returns A React node that re-renders itself with each yielded value, completion or error, and formatted by the child render function passed into `children` (or just the yielded value as-is in the absent of it). * * @see {@link IterationResult `IterationResult`} * * @example * ```tsx * // With the `initialValue` prop and showing usage of all properties of the iteration object * // within the child render function: * * import { Iterate } from 'react-async-iterators'; * * function SelfUpdatingTodoList(props) { * return ( * <div> * <h2>My TODOs</h2> * * <Iterate initialValue={[]} value={props.todosAsyncIter}> * {todosNext => * todosNext.pendingFirst ? ( * <div>Loading first todos...</div> * ) : ( * <> * {todosNext.error ? ( * <div>An error was encountered: {todosNext.error.toString()}</div> * ) : ( * todosNext.done && <div>No additional updates for todos are expected</div> * )} * * <ul> * {todosNext.map(todo => ( * <li key={todo.id}>{todo.text}</li> * ))} * </ul> * </> * ) * } * </Iterate> * </div> * ); * } * ``` */ function Iterate(props) { const renderOutput = typeof props.children === 'function' ? (() => { const propsBetterTyped = props; const next = (0, index_js_1.useAsyncIter)(propsBetterTyped.value, propsBetterTyped.initialValue); return propsBetterTyped.children(next); })() : (() => { const propsBetterTyped = props; const next = (0, index_js_1.useAsyncIter)(propsBetterTyped.children, propsBetterTyped.initialValue); return next.value; })(); return renderOutput; } //# sourceMappingURL=index.js.map