Skip to content

Latest commit

 

History

History
246 lines (181 loc) · 6.67 KB

provider.md

File metadata and controls

246 lines (181 loc) · 6.67 KB
id title sidebar_label
provider
<Provider />
Provider

Overview

The <Provider /> component makes one or multiple PouchDB databases available to any nested components' hooks.

You can't use the hooks unless they are invoked from a component nested inside of a <Provider />.

Most apps will render the <Provider /> as one of the most top level components, with the entire app's component tree inside of it. But they can be nested.

Every <Provider /> has a default database. The default database is used whenever the db option of the hooks is not used. This db-option selects the database the hook will use. For a single database <Provider /> that database is the default. A multi database <Provider /> requires a default prop that selects the default database by it's key.

If a <Provider /> is nested inside of another <Provider />, the child will merge the databases of the parent into it's databases set. But overwrites any database with conflicting keys. The default is also overwritten.

For overwriting databases the child <Provider /> uses Object.assign({}, parentDBs, ownDBs). The child shadows the parent.

Props

<Provider /> has two sets of props:

  • single database
  • multi databases

Props single database

pouchdb (PouchDB database) The PouchDB database you want to provide to the child components.

name (String optional) Name to use when selecting that database with a hook's db option. Defaults to the name field of the database.

children (ReactElement) The root of your component hierarchy, which should have access to this database.

Props multi databases

databases (Object) Object of PouchDB databases. The key used, is the key by which a database can be selected at the db options of hooks.

default (String) Key of the default database. This can also be the key of a parent database. Required.

children (ReactElement) The root of your component hierarchy, which should have access to this database.

Example Usage

In the Examples below <App /> is the top most component, that contains all of your app.

Vanilla React Example

import React from 'react'
import ReactDOM from 'react-dom'
import PouchDB from 'pouchdb-browser'
import { Provider } from 'use-pouchdb'

import { App } from './App'

const db = new PouchDB('local')

ReactDOM.render(
  <Provider pouchdb={db}>
    <App />
  </Provider>,
  document.getElementById('root')
)

Multiple databases

Hooks access the local database if undefined, null, "_default" or "local" is passed to their db option. To access the remote database you must pass remote to the hook's db option.

To change the default database, change the default's value. All hooks that access the default database will re-query, using the new default database, while still returning the old content.

This pattern can be used for the first visit: Use the remote db when no local data exist. But sync in the background. Once all data is locally available, fetch all used views and indexes on the local db, which will start the indexing. And then switch to the local db.

import React from 'react'
import ReactDOM from 'react-dom'
import PouchDB from 'pouchdb-browser'

import { Provider } from 'use-pouchdb'

import App from './App'

const db = new PouchDB('local_data')
const remoteDb = new PouchDB('https://example.com/db')

ReactDOM.render(
  <Provider
    default="local"
    databases={{
      local: db,
      remote: remoteDb,
    }}
  >
    <App />
  </Provider>,
  document.getElementById('root')
)

Usage with React Router

I recommend using usePouchDB with an routing solution, like React Router.

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import PouchDB from 'pouchdb-browser'
import { Provider } from 'use-pouchdb'

import { App } from './App'
import { Other } from './Other'
import { More } from './More'
import { Header } from './Header'

const db = new PouchDB('local')

ReactDOM.render(
  <Provider pouchdb={db}>
    <Router>
      <Header />

      <Switch>
        <Route path="/other">
          <Other />
        </Route>

        <Route path="/more">
          <More />
        </Route>

        <Route path="/">
          <App />
        </Route>
      </Switch>
    </Router>
  </Provider>,
  document.getElementById('root')
)

With Redux and React-Redux

There are also some Redux-PouchDB packages, for example redux-pouchdb.

Read more about Redux and React-Redux at their sites.

import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import PouchDB from 'pouchdb-browser'
import { Provider as PouchProvider } from 'use-pouchdb'

import { App } from './App'
import createStore from './createReduxStore'

const store = createStore()

const db = new PouchDB('local')

ReactDOM.render(
  <Provider store={store}>
    <PouchProvider pouchdb={db}>
      <App />
    </PouchProvider>
  </Provider>,
  document.getElementById('root')
)

While you don't need to use Redux and can build full apps using only usePouchDB. You might already use Redux. Or if you want to share complicated derived state between multiple components Redux might be a tool for you.

You can use both at the same time.

Extending the context

Databases can be made available to a subtree, while still be able to access all other databases.

import React from 'react'
import ReactDOM from 'react-dom'
import PouchDB from 'pouchdb-browser'
import { Provider } from 'use-pouchdb'

import { Main } from './Main'
import { UserMenu } from './UserMenu'

const db = new PouchDB('local')

ReactDOM.render(
  <Provider pouchdb={db}>
    <div>
      <Main />
      <UserMenu />
    </div>
  </Provider>,
  document.getElementById('root')
)

and in UserMenu.js:

import React from 'react'
import PouchDB from 'pouchdb-browser'
import { Provider } from 'use-pouchdb'

// Menu will only have access to the remote database
import Menu from './Menu'

const remote = new PouchDB('https://example.com/db')

export function UserMenu() {
  return (
    <Provider pouchdb={remote} name="remote">
      <Menu />
    </Provider>
  )
}

Hooks in <Menu /> access the remote database by default, or if you pass undefined, null, "remote" or "_default" to the db option. You can still access the local database if you pass "local" into the db option.