refactor protocol provider to use reducer
This commit is contained in:
parent
80de6eae00
commit
9e516ef773
|
@ -1,6 +1,6 @@
|
||||||
export { ClientProvider } from './provider'
|
export { ProtocolProvider, useProtocol } from './provider'
|
||||||
export { useCommunity } from './use-community'
|
|
||||||
export { useChats } from './use-chats'
|
|
||||||
export { useChannel, Channel } from './use-channel'
|
|
||||||
export { useAccount } from './use-account'
|
export { useAccount } from './use-account'
|
||||||
|
export type { Chat } from './use-chat'
|
||||||
|
export { useChat } from './use-chat'
|
||||||
|
export { useChats } from './use-chats'
|
||||||
export { useMembers } from './use-members'
|
export { useMembers } from './use-members'
|
||||||
|
|
|
@ -1,101 +1,109 @@
|
||||||
import React, {
|
import React, { createContext, useContext, useEffect, useReducer } from 'react'
|
||||||
createContext,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useState,
|
|
||||||
} from 'react'
|
|
||||||
|
|
||||||
import { createClient } from '@status-im/js'
|
import { createClient } from '@status-im/js'
|
||||||
|
|
||||||
import { Loading } from '~/src/components/loading'
|
import { Loading } from '~/src/components/loading'
|
||||||
|
|
||||||
import type { Account, Client, ClientOptions, Community } from '@status-im/js'
|
import type { Account, Client, ClientOptions, Community } from '@status-im/js'
|
||||||
import type { Config } from '~/src/types/config'
|
|
||||||
|
|
||||||
const Context = createContext<Client | undefined>(undefined)
|
const Context = createContext<State | undefined>(undefined)
|
||||||
const CommunityContext = createContext<
|
|
||||||
Community['communityMetadata'] | undefined
|
|
||||||
>(undefined)
|
|
||||||
|
|
||||||
export function useClient() {
|
type State = {
|
||||||
const context = useContext(Context)
|
loading: boolean
|
||||||
|
client: Client | undefined
|
||||||
if (!context) {
|
community: Community['communityMetadata'] | undefined
|
||||||
throw new Error(`useClient must be used within a ClientProvider`)
|
account: Account | undefined
|
||||||
|
dispatch?: React.Dispatch<Action>
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
type Action =
|
||||||
}
|
| { type: 'INIT'; client: Client }
|
||||||
|
| { type: 'UPDATE_COMMUNITY'; community: Community['communityMetadata'] }
|
||||||
|
| { type: 'SET_ACCOUNT'; account: Account }
|
||||||
|
| { type: 'REMOVE_ACCOUNT' }
|
||||||
|
|
||||||
export function useCommunity() {
|
interface Props {
|
||||||
const context = useContext(CommunityContext)
|
|
||||||
|
|
||||||
if (!context) {
|
|
||||||
// return {}
|
|
||||||
throw new Error(`useCommunity must be used within a ClientProvider`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ClientProviderProps {
|
|
||||||
options: ClientOptions
|
options: ClientOptions
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ClientProvider = (props: ClientProviderProps) => {
|
const reducer = (state: State, action: Action): State => {
|
||||||
const [client, setClient] = useState<Client>()
|
switch (action.type) {
|
||||||
const [community, setCommunity] = useState<Community['communityMetadata']>()
|
case 'INIT': {
|
||||||
const [account, setAccount] = useState<Account>()
|
const { client } = action
|
||||||
const [loading, setLoading] = useState(true)
|
return {
|
||||||
|
...state,
|
||||||
|
loading: false,
|
||||||
|
client,
|
||||||
|
community: client.community.communityMetadata,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'UPDATE_COMMUNITY': {
|
||||||
|
return { ...state, community: action.community }
|
||||||
|
}
|
||||||
|
case 'SET_ACCOUNT': {
|
||||||
|
return { ...state, account: action.account }
|
||||||
|
}
|
||||||
|
case 'REMOVE_ACCOUNT': {
|
||||||
|
return { ...state, account: undefined }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProtocolProvider = (props: Props) => {
|
||||||
const { options, children } = props
|
const { options, children } = props
|
||||||
|
|
||||||
// const client = useMemo(() => {
|
const [state, dispatch] = useReducer(reducer, {
|
||||||
// return createClient(options)
|
loading: true,
|
||||||
// }, [options])
|
client: undefined,
|
||||||
|
community: undefined,
|
||||||
|
account: undefined,
|
||||||
|
dispatch: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { client, loading } = state
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadClient = async () => {
|
const loadClient = async () => {
|
||||||
// setLoading(true)
|
const client = await createClient({ publicKey: options.publicKey })
|
||||||
const client = await createClient({ publicKey: props.options.publicKey })
|
dispatch({ type: 'INIT', client })
|
||||||
console.log('init', client)
|
|
||||||
setCommunity(client.community.communityMetadata)
|
|
||||||
console.log(
|
|
||||||
'file: provider.tsx > line 64 > loadClient > client.community.communityMetadata',
|
|
||||||
client.community.communityMetadata
|
|
||||||
)
|
|
||||||
|
|
||||||
setClient(client)
|
|
||||||
setLoading(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadClient()
|
loadClient()
|
||||||
}, [])
|
|
||||||
|
// Community public key should not change during the lifetime
|
||||||
|
}, []) // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (client) {
|
if (client) {
|
||||||
console.log('useEffect subscribe')
|
|
||||||
return client.community.onCommunityUpdate(community => {
|
return client.community.onCommunityUpdate(community => {
|
||||||
setCommunity(community)
|
dispatch({ type: 'UPDATE_COMMUNITY', community })
|
||||||
console.log(
|
|
||||||
'file: provider.tsx > line 75 > useEffect > community',
|
|
||||||
community
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [client])
|
}, [client])
|
||||||
|
|
||||||
// if (!client) {
|
if (loading) {
|
||||||
// return
|
return <Loading />
|
||||||
// }
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Context.Provider value={client}>
|
<Context.Provider value={{ ...state, dispatch }}>
|
||||||
<CommunityContext.Provider value={community}>
|
{children}
|
||||||
{loading ? <Loading /> : children}
|
|
||||||
</CommunityContext.Provider>
|
|
||||||
</Context.Provider>
|
</Context.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useProtocol() {
|
||||||
|
const context = useContext(Context)
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(`useProtocol must be used within a ProtocolProvider`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// we enforce initialization of client before rendering children
|
||||||
|
return context as State & {
|
||||||
|
client: Client
|
||||||
|
community: Community['communityMetadata']
|
||||||
|
dispatch: React.Dispatch<Action>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue