Skip to content

Commit

Permalink
examples: handle unmount in web-wa-sqlite example. (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
thruflo committed Aug 9, 2023
1 parent 8e87c34 commit 0ab0429
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 43 deletions.
59 changes: 42 additions & 17 deletions examples/web-wa-sqlite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,32 @@ The main code to look at is in [`./src/Example.tsx`](./src/Example.tsx):
```tsx
export const Example = () => {
const [ electric, setElectric ] = useState<Electric>()

useEffect(() => {
let isMounted = true

const init = async () => {
const config = {
auth: {
token: await localAuthToken()
}
}

const conn = await ElectricDatabase.init('electric.db', '')
const db = await electrify(conn, schema, config)
setElectric(db)
const electric = await electrify(conn, schema, config)

if (!isMounted) {
return
}

setElectric(electric)
}

init()

return () => {
isMounted = false
}
}, [])

if (electric === undefined) {
Expand All @@ -139,37 +157,44 @@ export const Example = () => {
}
```

This opens an electrified database client and passes it to the application using the React Context API. Components can then use the [`useElectric`](https://electric-sql.com/docs/usage/frameworks#useelectric-hook) and `useLiveQuery` hooks to access the database client and bind reactive queries to the component state.
This opens an electrified database client and passes it to the application using the React Context API. Components can then use the [`useElectric`](https://electric-sql.com/docs/integrations/frontend/react#useelectric) and [`useLiveQuery`](https://electric-sql.com/docs/integrations/frontend/react#uselivequery) hooks to access the database client and bind reactive queries to the component state.

```tsx
const ExampleComponent = () => {
const { db } = useElectric()!
const { results } = useLiveQuery(db.items.liveMany({})) // read all items

// read all items
const { results } = useLiveQuery(
db.items.liveMany()
)

const addItem = async () => {
await db.items.create({
data: {
value: crypto.randomUUID(),
value: genUUID(),
}
})
}

const clearItems = async () => {
await db.items.deleteMany() // delete all items
// delete all items
await db.items.deleteMany()
}


const items: Item[] = results !== undefined ? results : []

return (
<div>
<div className='controls'>
<button className='button' onClick={addItem}>
<div className="controls">
<button className="button" onClick={addItem}>
Add
</button>
<button className='button' onClick={clearItems}>
<button className="button" onClick={clearItems}>
Clear
</button>
</div>
{results && results.map((item: any, index: any) => (
<p key={ index } className='item'>
{items.map((item: any, index: any) => (
<p key={ index } className="item">
<code>{ item.value }</code>
</p>
))}
Expand Down Expand Up @@ -214,8 +239,8 @@ Now, let's update the app. In `Example.tsx`, modify the `addItem` function to pr
const addItem = async () => {
await db.items.create({
data: {
value: crypto.randomUUID(),
other_value: crypto.randomUUID(), // <-- insert value in new row
value: genUUID(),
other_value: genUUID(), // <-- insert value in new row
}
})
}
Expand All @@ -224,8 +249,8 @@ const addItem = async () => {
Also modify the returned HTML to display the value of the new column:

```typescript jsx
{results && results.map((item: any, index: any) => (
<p key={ index } className='item'>
{items.map((item: any, index: any) => (
<p key={ index } className="item">
<code>{ item.value } - { item.other_value }</code>
</p>
))}
Expand Down
76 changes: 50 additions & 26 deletions examples/web-wa-sqlite/src/Example.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,52 @@
import React, { useEffect, useState } from 'react'
import './Example.css'

import { schema, Electric } from './generated/client'
import { electrify, ElectricDatabase } from 'electric-sql/wa-sqlite'
import { makeElectricContext, useLiveQuery } from 'electric-sql/react'
import { ElectricDatabase, electrify } from 'electric-sql/wa-sqlite'

import { authToken } from 'electric-sql/auth'
import { genUUID } from 'electric-sql/util'

import { Electric, Item, schema } from './generated/client'

import './Example.css'

const { ElectricProvider, useElectric } = makeElectricContext<Electric>()

const localAuthToken = (): Promise<string> => {
const issuer = 'local-development'
const signingKey = 'local-development-key-minimum-32-symbols'

return authToken(issuer, signingKey)
}

export const Example = () => {
const [ electric, setElectric ] = useState<Electric>()

useEffect(() => {
let isMounted = true

const init = async () => {
const conn = await ElectricDatabase.init('electric.db', '')
const db = await electrify(conn, schema, {
const config = {
auth: {
token: await authToken('local-development', 'local-development-key-minimum-32-symbols')
token: await localAuthToken()
}
})
setElectric(db)
// Calling `.sync()` methods is possible here, right after init:
// await db.db.items.sync()
}

const conn = await ElectricDatabase.init('electric.db', '')
const electric = await electrify(conn, schema, config)

if (!isMounted) {
return
}

setElectric(electric)
}

init()

return () => {
isMounted = false
}
}, [])

if (electric === undefined) {
Expand All @@ -40,19 +62,19 @@ export const Example = () => {

const ExampleComponent = () => {
const { db } = useElectric()!
// Or here, in a `useEffect` without dependencies to limit it running once per component render.

useEffect(() => void db.items.sync(), [])

// `useliveQuery` will keep this variable up to data with the SQLite database, but to get data from server into SQLite
// you need to call `.sync()`, as demonstrated on the line above
const { results } = useLiveQuery(db.items.liveMany({})) // select all
const { results } = useLiveQuery(
db.items.liveMany()
)

const addItem = async () => {
await db.items.create({
data: {
value: crypto.randomUUID(),
value: genUUID(),
// uncomment the line below after migration
//other_value: crypto.randomUUID(),
//other_value: genUUID(),
}
})
}
Expand All @@ -61,19 +83,21 @@ const ExampleComponent = () => {
await db.items.deleteMany() // delete all items
}

const items: Item[] = results ?? []

// After the migration, comment out this code and uncomment code block below
return (
<div>
<div className='controls'>
<button className='button' onClick={addItem}>
<div className="controls">
<button className="button" onClick={addItem}>
Add
</button>
<button className='button' onClick={clearItems}>
<button className="button" onClick={clearItems}>
Clear
</button>
</div>
{results && results.map((item: any, index: any) => (
<p key={ index } className='item'>
{items.map((item: any, index: any) => (
<p key={ index } className="item">
<code>{ item.value }</code>
</p>
))}
Expand All @@ -83,16 +107,16 @@ const ExampleComponent = () => {
// Uncomment after migration
//return (
// <div>
// <div className='controls'>
// <button className='button' onClick={addItem}>
// <div className="controls">
// <button className="button" onClick={addItem}>
// Add
// </button>
// <button className='button' onClick={clearItems}>
// <button className="button" onClick={clearItems}>
// Clear
// </button>
// </div>
// {results && results.map((item: any, index: any) => (
// <p key={ index } className='item'>
// {items.map((item: any, index: any) => (
// <p key={ index } className="item">
// <code>{ item.value } - { item.other_value }</code>
// </p>
// ))}
Expand Down

0 comments on commit 0ab0429

Please sign in to comment.