IndexedDB – Une base de données dans le navigateur (partie 2)
Lorsque le stockage local et les cookies atteignent leurs limites, lorsque la nature bloquante des threads ralentit votre application, il est temps de passer à IndexDB. Mais pourquoi vivre avec l'API de bas niveau qui peut être maladroit pour se faire comprendre? Accédez à PouchDB et commencez à tirer parti de ce stockage de navigateur asynchrone et performant aujourd'hui.
Il existe de nombreuses manières de stocker des données côté client. Nous avons couvert Stockage, sessionStorage et les cookies dans Partie 1 de cet article mais ce n'est pas là que ça se termine! Les navigateurs modernes proposent une autre approche du stockage des données côté client, offrant des lectures et des écritures asynchrones avec une interface légèrement confuse. De quoi est-ce que je parle? Non, pas Web SQL, qui est déconseillé et ne doit pas être utilisé. Je parle de IndexedDB !
Dans cet article, nous verrons comment utiliser IndexedDB (avec la bibliothèque PouchDB) pour stocker des brouillons pouvant ensuite être synchronisés avec notre API à être stocké en permanence. Fermer accidentellement votre navigateur? Jamais peur! Le projet a été mis à l'abri dans IndexedDB.
Le code source de ce projet est disponible sur https://github.com/leighhalliday/leigh-notes-web . La version finale de cette application se trouve à https://leigh-notes-web.herokuapp.com/ .
Interface difficile
J'ai mentionné ci-dessus qu'il est difficile de travailler avec IndexedDB, et même cette explication utilise une API légèrement modifiée (qui a été promise) pour interagir avec elle. Pour cette raison, de nombreuses personnes ont créé des bibliothèques construites sur IndexedDB pour simplifier les choses. Les bibliothèques populaires comprennent localForage Dexie.js BID-keyval et la bibliothèque que nous allons couvrir dans cet article, PouchDB . .
Connexion à la base de données
De la même manière que le code serveur / côté serveur doit se connecter à la base de données, nous devons également nous connecter à notre base de données PouchDB. Comme il s'agit d'un code spécifique au client et que Next.js est également exécuté sur le serveur, j'ai une vérification en place pour ne renvoyer une connexion à la base de données que si nous sommes dans le navigateur. nous vous suggérons de vous connecter à une note appelée "notes", qui sera créée si elle n'existe pas encore.
import PouchDB de "pouchdb" ;
const getDb = () => {
if ( processus . navigateur ) {
return new PouchDB ( "notes" { auto_compaction : true } ) ;
}
} ;
Jusqu'à présent, le composant que nous construisons et qui donne aux notes l'aspect suivant:
class Index s'étend Réagissez . Composant {[19659043] statique async getInitialProps ( { jeton } ) {
retour { jeton } ;
}
state = {
draftNotes : {}
savedNotes : {}
} ;
db = getDb () ;
}
Lecture des notes
Lorsque notre composant est monté, nous souhaitons charger le DraftNotes
. ] de PouchDB et peupler l'état avec eux.
composantDidMount () {
ceci . loadDraftNotes () ;
this . loadSavedNotes ()
}
La fonction loadDraftNotes
est lue en premier tousDocs
. le DB qui nous rend un objet résultat. Après avoir extrait le doc
(la note réelle) de chaque ligne, puis l'avoir inversé pour que le dernier projet de note figure en haut de la liste, nous pouvons le placer dans l'état.
loadDraftNotes = async () => {
const result = attend ceci . est vide. db . allDocs ( { include_docs : true } ) ;
const = résultat . rangées . carte ( rangée => rangée . . doc ]) . reverse () ;
ceci . setState ( { projetNotes } ) ;
} ;
Ajout et mise à jour de notes
Lors de la création d'une nouvelle note, vous devez disposer d'un colonne unique _id
requise par PouchDB… nous utilisons une chaîne ISO de la date actuelle dans ce cas. Tout d'abord, nous allons annexer l'état draftNotes, en ajoutant notre nouvelle note au début du tableau, puis appeler la fonction db.put (note)
qui insère la nouvelle note dans la base de données.
createNote = () => { const note = { _id : new Date () . toISOString ()
body : "" } ; const draftNotes = [ note ... . ] this . state . draftNotes ] ; cette . setState ( { draftNotes } ) ; ceci . db . put ( note ) ; ]} ;
La mise à jour est légèrement plus compliquée que l'insertion, mais ce n'est pas si mal! Étant donné l'index
de la note de notre tableau draftNotes
et le corps mis à jour, nous pouvons tout d'abord mettre à jour l'état (avec un peu d'aide de la bibliothèque immuable Immer).
Après En mettant à jour l'état, nous allons utiliser l'index pour trouver la propriété _id
nécessaire à PouchDB pour le lire dans la base de données. Après avoir lu la note de la base de données, nous pouvons mettre à jour sa propriété body
puis appeler put
pour mettre à jour la base de données avec nos modifications.
Même si nous avons utilisé le put
pour insérer une nouvelle note et mettre à jour une note existante, PouchDB est assez intelligent pour savoir laquelle vous essayez de faire en raison de son attribut unique _id
.
updateNote = async ( index corps ) => {
ce . set-state (
produire ( draft => {
draft . draftNotes [ index ] . body = corps ;
} ) [19659034]) ;
const noteId = cette . état . projet de notes [ index ] . _id ;
const note = attend cette . db . . 19659012] ( noteId ) ;
note . body = body ;
cette . db . mis [1359000] note ) ;
} ;
Suppression des notes
À un moment donné, vous voudrez peut-être enregistrer vos brouillons sur le serveur. Dans cet exemple, j'ai appelé sync
.
- Publiez la note via AJAX sur notre API, enregistrez-la dans notre base de données de production.
- Supprimez la note de la base PouchDB locale
. Après avoir parcouru toutes les notes, nous peut appeler loadDraftNotes
et loadSavedNotes
à nouveau pour rafraîchir l'état.
syncNotes = async () (19659012) = = ] {
const promet = ce . état . projetNotes
. filtre ( note => note . corps )
. carte [19659]. 19659146] async note => {
attend cette . postNoteToApi ( note ) ; ] attendez ce . deleteNote ( note ) ;
} ) ;
wait wait Promise . all ( promesses ) ;
ceci . loadDraftNotes () ] this . loadSavedNotes () ;
} ;
De nombreuses promesses se réalisent ici! Vous vous retrouvez avec un tableau d'entre eux et, avec vous attendez Promise.all (promises)
vous pouvez attendre qu'ils soient tous résolus. Jetons un coup d’œil à ce que postNoteToApi (note)
fait. C'est une requête POST AJAX assez simple qui utilise Axios avec l'API, transmettant le jeton JWT dans l'en-tête Authorization afin qu'il sache qui nous sommes.
postNoteToApi = note => [19659016] {
const { jeton } = ce . étais ;
retour Axios . post (
"https://leigh-notes-api.herokuapp.com/notes"
{
note : { body : note . body }
}
{ en-têtes : { Autorisation : `Porteur: $ { jeton } ` ]}
) ;
} ;
Une fois que nous avons posté la note sur l'API, nous pouvons la supprimer de notre PouchDB local, qui est ce que deleteNote (note )
fait:
deleteNote = async note => {
const doc = à attendre this . db . get ( note . _id ) ;
à attendre cette [19659012]. db . remove ( doc ) ;
} ;
Les notes UI
Nous ' J'ai beaucoup regardé l'indiv fonctions habituelles jusqu’à présent, mais nous n’avons pas encore jeté un œil à quoi ressemble l’interface utilisateur, ce qui est réellement rendu.
rend () {
const { jeton } = ce . accessoires ;
const { projet de notes
Source link