useAllDocs
Overview
useAllDocs is the hook version of db.allDocs(). It gives you the
ability to fetch multiple documents by their ids.
It doesn't need the creation of a secondary index. This means that it is useable right away, even when not all documents did sync.
As all hooks, it subscribes to updates.
useAllDocs can only be invoked from a component nested inside of a <Provider />.
Parameters
useAllDocs expects a single options object. It has the same options as
db.allDocs(). Options descriptions are copied from the PouchDB API
page.
options: object-db.allDocs()option object.options.include_docs?: boolean- Include the document itself in each row in thedocfield. Otherwise by default you can only get the_idand_revproperties.options.conflicts?: boolean- Include conflict information in the_conflictsfield of a doc.options.attachments?: boolean- Include attachment data as base64-encoded string.options.binary?: boolean- Return attachment data as Blobs, instead of as base64-encoded strings.options.startkey?: string- Get documents with IDs in a certain range. The range starts with this key.options.endkey?: string- Get documents with IDs in a certain range. The range ends with this key.options.inclusive_end?: boolean- Include documents having an ID equal to the givenoptions.endkey. Default istrue.options.limit?: number- Maximum number of documents to return.options.skip?: number- Number of documents to skip before returning (warning: poor performance!).options.descending?: boolean- Reverse the order of the output documents. Note that the order ofoptions.startkeyandoptions.endkeyis reversed whendescendingistrue.options.key?: string- Only return documents with IDs matching this string key.options.keys?: string[]- Fetch multiple known IDs in a single shot.- Neither
options.startkeynoroptions.endkeycan be specified with this option. - The rows are returned in the same order as in the supplied
keysarray. - The row for a deleted document will have the revision ID of the deletion, and an extra key
deleted: truein thevalueproperty. - The row for a nonexistent document will only contain an
errorproperty with the value"not_found". - For more details, see the
db.allDocs() documentationor the CouchDB query options documentation.
- Neither
options.update_seq?: boolean- Include anupdate_seqvalue indicating which sequence id of the underlying database the view reflects.options.db?: string- Selects the database to be used. The database is selected by it's name/key. The special key"_default"selects the default database. Defaults to"_default".
keysis check for equality with a deep equal algorithm. And only if it differentiate by value will it cause a new query be made.
Result
useAllDocs results an object with those fields:
rows: object[]- Array of objects that contain the requested information. Empty during the first fetch or during an error. Each object has following fields:id: string-_idof the document.key: string-_idof the document.value: object- Object with one field:value.rev: string-_revof the document.
doc?: PouchDB.Core.Document- Ifoptions.include_docswastrue, this field will contain the document. And ifattachmentsis alsotrue, the document will contain the attachment data in the"_attachments"field.
offset: number- Theskipprovided.total_rows: number- The total number of non-deleted documents in the database.update_seq?: number | string- Ifupdate_seqistrue, this will contain the sequence id of the underlying database.state: 'loading' | 'done' | 'error'- Current state of the hook.loading- It is loading the documents. Or it is loading the updated version of them.done- The documents are loaded, and no update is being loaded.error- There was an error with fetching the documents. Look into theerrorfield.
loading: boolean- It is loading. The state isloading. This is only a shorthand.error: PouchDB.Error | null- If there was an error, then this field will contain the error. The error is reset tonullonce a fetch was successful.
Example Usage
useAllDocs is useful for many operations where you need to load multiple documents.
Prefix search
If you sort your documents by _id, then you can use useAllDocs to load all documents with a prefix. Read more
at the 12 pro tips section 7.
The '\ufff0' is a special high Unicode character, that is sorted after most others.
If a document, that fall into this range, gets added, updated or deleted, then the rows will be updated
accordingly.
import React from "react";
import { useAllDocs } from "use-pouchdb";
import { ErrorMessage } from "./ErrorMessage";
export function Comments({ id }) {
const commentsPrefix = `comments_${id}`;
const { rows, loading, state, error } = useAllDocs({
startkey: commentsPrefix,
endkey: commentsPrefix + "\ufff0",
include_docs: true,
});
if (state === "error") {
return <ErrorMessage error={error} />;
}
if (loading && rows.length === 0) {
return null;
}
return (
<div>
<h4>Comments</h4>
<div>
{rows.map((row) => (
<section key={row.id}>
<h5>{row.doc.username} commented</h5>
{!row.value.rev.startsWith("1-") && <span>Edited</span>}
<p>{row.doc.comment}</p>
</section>
))}
</div>
</div>
);
}
Load multiple documents by id
useAllDocs can also load multiple documents by their IDs.
import React from "react";
import { useAllDocs } from "use-pouchdb";
import { ErrorMessage } from "./ErrorMessage";
export function Related({ doc }) {
const { rows, loading, state, error } = useAllDocs({
keys: doc.related || [], // doc.related is an Array of IDs.
include_docs: true,
});
if (state === "error") {
return <ErrorMessage error={error} />;
}
if (loading && rows.length === 0) {
return null;
}
return (
<div>
<h4>Read more</h4>
<ul>
{rows.map((row) => (
<li key={row.id}>{row.doc.title}</li>
))}
</ul>
</div>
);
}
Descending
It is imported to remember that options.startkey and options.endkey switch, when options.descending is true.
import React from "react";
import { useAllDocs } from "use-pouchdb";
import ms from "milliseconds";
import { ErrorMessage } from "./ErrorMessage";
export function LastBookings() {
const midnight = new Date();
midnight.setHours(0);
midnight.setMinutes(0);
midnight.setSeconds(0);
// this goes from midnight to 7 days ago.
const { rows, loading, state, error } = useAllDocs({
// start midnight
startkey: "bookings_" + midnight.toJSON(),
// End at endkey
// the date 7 days ago is the end.
endkey: "bookings_" + new Date(midnight.getTime() - ms.days(7)).toJSON(),
include_docs: true,
descending: true,
});
if (state === "error") {
return <ErrorMessage error={error} />;
}
if (loading && rows.length === 0) {
return null;
}
return (
<div>
<h4>Bookings</h4>
<ul>
{rows.map((row) => (
<li key={row.id}>
{row.doc.amount}€ from {row.doc.partner}
</li>
))}
</ul>
</div>
);
}
Select a database
import React from "react";
import { useAllDocs } from "use-pouchdb";
import { ErrorMessage } from "./ErrorMessage";
export function Comments({ id, isLocalReady }) {
const commentsPrefix = `comments_${id}`;
const { rows, loading, state, error } = useAllDocs({
startkey: commentsPrefix,
endkey: commentsPrefix + "\ufff0",
include_docs: true,
// Select the database used
db: isLocalReady ? "local" : "remote",
});
if (state === "error") {
return <ErrorMessage error={error} />;
}
if (loading && rows.length === 0) {
return null;
}
return (
<div>
<h4>Comments</h4>
<div>
{rows.map((row) => (
<section key={row.id}>
<h5>{row.doc.username} commented</h5>
{!row.value.rev.startsWith("1-") && <span>Edited</span>}
<p>{row.doc.comment}</p>
</section>
))}
</div>
</div>
);
}