initial commit
This commit is contained in:
commit
0024f44c80
34 changed files with 1991 additions and 0 deletions
76
frontend/src/state.js
Normal file
76
frontend/src/state.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import React from 'react'
|
||||
import { reducer, action, CONNECTION_STATE, INITIAL_STATE } from '../../common/state.mjs'
|
||||
|
||||
function getConfig () {
|
||||
return {
|
||||
endpoint: process.env.NODE_ENV === 'development' ? 'http://localhost:3030' : ''
|
||||
}
|
||||
}
|
||||
function useConfig () {
|
||||
return getConfig()
|
||||
}
|
||||
|
||||
export function useCommand (defaultCommand, defaultArgs = {}) {
|
||||
const config = useConfig()
|
||||
const url = config.endpoint + '/command'
|
||||
const headers = { 'content-type': 'application/json' }
|
||||
const [pending, setPending] = React.useState(false)
|
||||
const [error, setError] = React.useState(null)
|
||||
const [success, setSuccess] = React.useState(null)
|
||||
return { pending, error, success, dispatch }
|
||||
async function dispatch (command = defaultCommand, args = defaultArgs) {
|
||||
setPending(true)
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
headers,
|
||||
method: 'post',
|
||||
body: JSON.stringify({ command, args })
|
||||
})
|
||||
const json = await res.json()
|
||||
if (json.error) throw new Error('Remote error: ' + json.details)
|
||||
setSuccess(json)
|
||||
} catch (err) {
|
||||
setError(error)
|
||||
} finally {
|
||||
setPending(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function useRemoteState (opts = {}) {
|
||||
const { retryInterval = 1000 } = opts
|
||||
const config = useConfig()
|
||||
const [retry, setRetry] = React.useState(0)
|
||||
const url = config.endpoint + '/sse'
|
||||
const [state, dispatch] = React.useReducer(reducer, INITIAL_STATE)
|
||||
const es = React.useRef()
|
||||
|
||||
function reconnect () {
|
||||
if (es.current) es.current.close()
|
||||
es.current = null
|
||||
setRetry(retry => retry + 1)
|
||||
}
|
||||
|
||||
// setup event source
|
||||
React.useEffect(() => {
|
||||
if (es.current) return
|
||||
es.current = new EventSource(url)
|
||||
}, [retry])
|
||||
|
||||
// process event source
|
||||
React.useEffect(() => {
|
||||
if (!es.current) return
|
||||
const eventSource = es.current
|
||||
eventSource.onmessage = (event) => {
|
||||
const action = JSON.parse(event.data)
|
||||
dispatch(action)
|
||||
}
|
||||
eventSource.onerror = () => {
|
||||
console.log('ONERROR!!')
|
||||
dispatch(action(CONNECTION_STATE, { error: `Failed to connect to backend` }))
|
||||
if (retryInterval) setTimeout(reconnect, retryInterval)
|
||||
}
|
||||
}, [es.current])
|
||||
|
||||
return { state }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue