diff --git a/README.md b/README.md index 3232777..eb8caaa 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ React hooks for the hypercore-protocol stack npm i use-hyper ``` -Warning: this is experimental, and API might change until v1. +Warning: this is experimental, and API might unexpectedly change until v1. ## Usage @@ -18,22 +18,32 @@ Every hook requires the related library installed: - `useDHT` depends on `@hyperswarm/dht-relay`. - `useSwarm` depends on `hyperswarm`. -If you import `useSwarm` then install this specific branch: +If you import `useSwarm` then install this specific branch:\ `npm i holepunchto/hyperswarm#add-swarm-session` ```javascript -import { useCore, useCoreEvent, useCoreWatch } from 'use-hyper' -import useDHT from 'use-hyper/dht' -import useSwarm from 'use-hyper/swarm' +import { useCore, useCoreWatch, useCoreEvent } from 'use-hyper/core' +import { DHT } from 'use-hyper/dht' +import { Swarm, useReplicate } from 'use-hyper/swarm' +import RAM from 'random-access-memory' const Child = () => { - const { core } = useCore() + const { core } = useCore() // Gets core from context + const { onwatch } = useCoreWatch() // Triggers re-render when core changes + useCoreEvent('append', () => console.log('on event', core.length)) - const { core } = useCoreWatch(['append', 'close']) // updates on append and close events + useReplicate(core) - const { core } = useCoreEvent('append', () => { - console.log(core) // do something - }) + const DHT = useDHT() // Gets DHT from the context + const swarm = useSwarm() // Same, from context + + return ( +
+ ID {core.id}
+ Length {core.length}
+ Peers {core.peers.length} +
+ ) } const App = () => { diff --git a/package.json b/package.json index 76ae76f..cc18720 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,6 @@ "url": "https://github.com/LuKks/use-hyper/issues" }, "homepage": "https://github.com/LuKks/use-hyper", - "peerDependencies": { - "react": "*", - "react-dom": "*" - }, "devDependencies": { "standard": "^17.0.0" }, diff --git a/src/core.js b/src/core.js index 3c3674b..2f15712 100644 --- a/src/core.js +++ b/src/core.js @@ -1,12 +1,6 @@ -import React, { - useEffect, - useState, - useRef, - useContext, - createContext -} from 'react' -import safetyCatch from 'safety-catch' +import React, { useEffect, useState, useRef, useContext, createContext } from 'react' import Hypercore from 'hypercore' +import safetyCatch from 'safety-catch' const CoreContext = createContext() @@ -27,10 +21,12 @@ export const Core = ({ children, storage, publicKey, ...options }) => { if (!storage) return const core = new Hypercore(storage, publicKey, options) - const onReady = () => setCore(core) - core.once('ready', onReady) + const onready = () => setCore(core) + core.once('ready', onready) + return () => { - core.off('ready', onReady) + core.off('ready', onready) + // + should setCore(null, core close)? core.close().catch(safetyCatch) } }, [storage, publicKey, ...deps]) @@ -63,28 +59,28 @@ export const useCoreEvent = (event, cb) => { }, [cb]) useEffect(() => { - if (!core || core?.closed) return + if (!core || core.closed) return - const listener = event => fn.current(event) + const listener = (a, b, c) => fn.current(a, b, c) core.on(event, listener) - return () => core.off(event, listener) - }, [event, core]) - return { core } + return () => core.off(event, listener) + }, [core, event]) } export const useCoreWatch = (events = EVENTS) => { const { core } = useCore() - const [, update] = useState(0) + const [onwatch, setUpdated] = useState(0) useEffect(() => { - if (!core || core?.closed) return + if (!core || core.closed) return - const onchange = () => update(i => i + 1) + const onchange = () => setUpdated(i => i + 1) events.forEach(event => core.on(event, onchange)) onchange() + return () => events.forEach(event => core.off(event, onchange)) }, [core, events]) - return { core } + return { onwatch } } diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 7a8f25f..0000000 --- a/src/index.js +++ /dev/null @@ -1,4 +0,0 @@ -export * from './dht.js' -export * from './key.js' -export * from './core.js' -export * from './swarm.js' diff --git a/src/swarm.js b/src/swarm.js index 0713ff3..12f7d8b 100644 --- a/src/swarm.js +++ b/src/swarm.js @@ -1,6 +1,6 @@ import React, { useEffect, useState, useContext, createContext } from 'react' -import safetyCatch from 'safety-catch' import Hyperswarm from 'hyperswarm' +import safetyCatch from 'safety-catch' import { useDHT } from './dht.js' const SwarmContext = createContext() @@ -42,36 +42,44 @@ export const useSwarm = () => { return context } -export const useReplicate = (core, enable = true, deps = []) => { +export const useReplicate = (core, deps = []) => { const { swarm } = useSwarm() + const [replicate, setReplicate] = useState(false) useEffect(() => { - if (!enable || !swarm || core?.closed) return + if (!swarm || !core || core.closed) return + let cleanup = false let session = null - let mounted = true - const onConnection = socket => { - core.replicate(socket) - } + const onsocket = socket => core.replicate(socket) + const ready = core.ready().catch(safetyCatch) + + ready.then(() => { + if (cleanup) return - core.ready().then(() => { - if (!mounted) return session = swarm.session({ keyPair: swarm.keyPair }) + + // + done could be outside of ready const done = core.findingPeers() - session.on('connection', onConnection) + session.on('connection', onsocket) session.join(core.discoveryKey, { server: false, client: true }) session.flush().then(done, done) + + setReplicate(true) }) return () => { - mounted = false + cleanup = true + if (!session) return - session.off('connection', onConnection) - session.leave(core.discoveryKey) + session.destroy().catch(safetyCatch) // Run on background + + // + should setReplicate(false, swarm destroy) first? + setReplicate(false) } - }, [swarm, core, enable, ...deps]) + }, [swarm, core, ...deps]) - return { swarm, core } + return { replicate } }