Skip to content

Commit

Permalink
make useHandle update the handle when the url changes
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffreylitt committed Dec 13, 2023
1 parent 9cc01a8 commit c2070a3
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 4 deletions.
10 changes: 6 additions & 4 deletions packages/automerge-repo-react-hooks/src/useHandle.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { AutomergeUrl, DocHandle } from "@automerge/automerge-repo"
import { useState } from "react"
import { useRepo } from "./useRepo.js"

/** A hook which returns a {@link DocHandle} identified by a URL.
*
* @remarks
* This requires a {@link RepoContext} to be provided by a parent component.
*/
export function useHandle<T>(automergeUrl: AutomergeUrl): DocHandle<T> {
export function useHandle<T>(docUrl?: AutomergeUrl): DocHandle<T> | undefined {
const repo = useRepo()
const [handle] = useState<DocHandle<T>>(repo.find(automergeUrl))
return handle
if (docUrl) {
return repo.find(docUrl)
} else {
return undefined
}
}
107 changes: 107 additions & 0 deletions packages/automerge-repo-react-hooks/test/useHandle.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { PeerId, Repo, AutomergeUrl } from "@automerge/automerge-repo"
import { DummyStorageAdapter } from "@automerge/automerge-repo/test/helpers/DummyStorageAdapter"
import { describe, it } from "vitest"
import { RepoContext } from "../src/useRepo"
import { useHandle } from "../src/useHandle"
import { renderHook } from "@testing-library/react-hooks"
import React, { useState } from "react"
import assert from "assert"

interface ExampleDoc {
foo: string
}

function getRepoWrapper(repo: Repo) {
return ({ children }) => (
<RepoContext.Provider value={repo}>{children}</RepoContext.Provider>
)
}

describe("useHandle", () => {
const repo = new Repo({
peerId: "bob" as PeerId,
network: [],
storage: new DummyStorageAdapter(),
})

function setup() {
const handleA = repo.create<ExampleDoc>()
handleA.change(doc => (doc.foo = "A"))

const handleB = repo.create<ExampleDoc>()
handleB.change(doc => (doc.foo = "B"))

return {
repo,
handleA,
handleB,
wrapper: getRepoWrapper(repo),
}
}

it("loads a handle", async () => {
const { handleA, wrapper } = setup()

const { result, waitForNextUpdate } = renderHook(
() => {
const handle = useHandle(handleA.url)

return {
handle,
}
},
{ wrapper }
)

assert.deepStrictEqual(result.current.handle, handleA)
})

it("returns undefined when no url given", async () => {
const { handleA, wrapper } = setup()

const { result, waitForNextUpdate } = renderHook(
() => {
const handle = useHandle()

return {
handle,
}
},
{ wrapper }
)

assert.deepStrictEqual(result.current.handle, undefined)
})

it("updates the handle when the url changes", async () => {
const { wrapper, handleA, handleB } = setup()

const { result, waitForNextUpdate } = renderHook(
() => {
const [url, setUrl] = useState<AutomergeUrl>()
const handle = useHandle(url)

return {
setUrl,
handle,
}
},
{ wrapper }
)

// initially doc is undefined
assert.deepStrictEqual(result.current.handle, undefined)

// set url to doc A
result.current.setUrl(handleA.url)
assert.deepStrictEqual(result.current.handle, handleA)

// set url to doc B
result.current.setUrl(handleB.url)
assert.deepStrictEqual(result.current.handle, handleB)

// set url to undefined
result.current.setUrl(undefined)
assert.deepStrictEqual(result.current.handle, undefined)
})
})

0 comments on commit c2070a3

Please sign in to comment.