Skip to content

Commit

Permalink
Fix circular dependency with Store and StreamrClientProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
tumppi committed Nov 14, 2024
1 parent 6e01cbc commit 01e65df
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 77 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"@ethersproject/hdnode": "^5.7.0",
"@ethersproject/providers": "^5.5.3",
"@ibm/plex": "^5.1.3",
"@streamr/config": "^5.4.0",
"@streamr/config": "^5.4.1",
"@streamr/sdk": "^101.1.2",
"@streamr/utils": "^101.1.2",
"@tanstack/react-query": "^5.28.4",
Expand Down
73 changes: 33 additions & 40 deletions src/Store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ import React, {
useReducer,
useState,
} from 'react'
import { useParams } from 'react-router-dom'
import { DefaultViewState } from './consts'
import { useGlobalKeyDownEffect, useMap, useStreamIdParam } from './hooks'
import { useGlobalKeyDownEffect, useMap } from './hooks'
import { ActiveView, ConnectionsMode, OperatorNode } from './types'
import { useHud } from './utils'
import { useOperatorNodesForStreamQuery } from './utils/nodes'
import { truncate } from './utils/text'
import { DEFAULT_CHAIN_ID, SUPPORTED_CHAIN_IDS } from './utils/chains'
import { DEFAULT_CHAIN_ID, getPersistedChainId, persistChainId } from './utils/chains'

interface UrlParams {
nodeId: string | null
streamId: string | null
}

interface Store {
chainId: number
Expand All @@ -31,6 +35,8 @@ interface Store {
publishers: Record<string, string | undefined>
searchPhrase: string
selectedNode: OperatorNode | null
urlParams: UrlParams
setUrlParams(value: UrlParams): void
setChainId(value: number): void
setActiveView(value: ActiveView): void
setConnectionsMode: Dispatch<SetStateAction<ConnectionsMode>>
Expand All @@ -50,6 +56,8 @@ const StoreContext = createContext<Store>({
publishers: {},
searchPhrase: '',
selectedNode: null,
urlParams: { nodeId: null, streamId: null },
setUrlParams: () => {},
setChainId: () => {},
setActiveView: () => {},
setConnectionsMode: () => {},
Expand All @@ -61,11 +69,11 @@ interface StoreProviderProps {
children?: ReactNode
}

// Add a constant for the storage key
const CHAIN_ID_STORAGE_KEY = 'network-explorer-chain-id'

export function StoreProvider(props: StoreProviderProps) {
const selectedNode = useNodeByNodeIdParam()
const [urlParams, setUrlParams] = useState<UrlParams>({
nodeId: null,
streamId: null,
})

const [locationParamKey, invalidateLocationParamKey] = useReducer((x: number) => x + 1, 0)

Expand All @@ -80,17 +88,7 @@ export function StoreProvider(props: StoreProviderProps) {
})
})

// Initialize chainId from localStorage
const [chainId, setChainId] = useState(() => {
const stored = localStorage.getItem(CHAIN_ID_STORAGE_KEY)

// Check if the stored value is a valid network chainId
if (stored && SUPPORTED_CHAIN_IDS.includes(parseInt(stored, 10))) {
return parseInt(stored, 10)
}

return DEFAULT_CHAIN_ID
})
const [chainId, setChainId] = useState(getPersistedChainId())

const [activeView, setActiveView] = useState<ActiveView>(ActiveView.Map)

Expand Down Expand Up @@ -119,12 +117,24 @@ export function StoreProvider(props: StoreProviderProps) {
[showConnections],
)

// Persist chainId changes
useEffect(() => {
localStorage.setItem(CHAIN_ID_STORAGE_KEY, chainId.toString())
console.log('Store: Chain ID changed:', chainId)
persistChainId(chainId)
}, [chainId])

const { streamId, nodeId: activeNodeId } = urlParams
const { data: nodes } = useOperatorNodesForStreamQuery(streamId || undefined, chainId)

const selectedNode = useMemo(
function findNodeById() {
if (!nodes || !activeNodeId) {
return null
}

return nodes.find(({ id }) => id === activeNodeId) || null
},
[activeNodeId, nodes],
)

return (
<StoreContext.Provider
{...props}
Expand All @@ -140,6 +150,8 @@ export function StoreProvider(props: StoreProviderProps) {
publishers,
searchPhrase: rawSearchPhrase,
selectedNode,
urlParams,
setUrlParams,
setChainId,
setActiveView,
setConnectionsMode,
Expand All @@ -153,22 +165,3 @@ export function StoreProvider(props: StoreProviderProps) {
export function useStore() {
return useContext(StoreContext)
}

function useNodeByNodeIdParam() {
const streamId = useStreamIdParam()

const { data: nodes } = useOperatorNodesForStreamQuery(streamId || undefined)

const { nodeId: activeNodeId = null } = useParams<{ nodeId: string }>()

return useMemo(
function findNodeById() {
if (!nodes || !activeNodeId) {
return null
}

return nodes.find(({ id }) => id === activeNodeId) || null
},
[activeNodeId, nodes],
)
}
25 changes: 21 additions & 4 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { QueryClientProvider } from '@tanstack/react-query'
import 'mapbox-gl/dist/mapbox-gl.css'
import React from 'react'
import React, { useEffect } from 'react'
import { MapProvider } from 'react-map-gl'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import { BrowserRouter, Route, Routes, useParams } from 'react-router-dom'
import styled, { css } from 'styled-components'
import { StoreProvider } from '../Store'
import { StoreProvider, useStore } from '../Store'
import {
useMap,
useSelectedNodeLocationEffect,
Expand Down Expand Up @@ -33,15 +33,32 @@ const LoadingIndicator = styled(UnstyledLoadingIndicator)`
z-index: 4;
`

function UrlParamsSynchronizer() {
const { nodeId, streamId } = useParams()
const { setUrlParams } = useStore()

useEffect(() => {
setUrlParams({
nodeId: nodeId || null,
streamId: streamId || null,
})
}, [nodeId, streamId, setUrlParams])

return null
}

function Page() {
const streamId = useStreamIdParam()

const isLoadingNodes = useIsFetchingOperatorNodesForStream(streamId || undefined)
const { chainId } = useStore()

const isLoadingNodes = useIsFetchingOperatorNodesForStream(streamId || undefined, chainId)

const { showNetworkSelector, showSearch, compact } = useHud()

return (
<>
<UrlParamsSynchronizer />
<PublisherDetector />
<Map />
<MapAutoUpdater />
Expand Down
5 changes: 4 additions & 1 deletion src/components/MapMarkerLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { useStreamIdParam } from '../hooks'
import { OperatorNode } from '../types'
import { NodeLayerId, NodeSourceId, getNodeLocationId } from '../utils/map'
import { useOperatorNodesForStreamQuery } from '../utils/nodes'
import { useStore } from '../Store'

const EmptyNodes: OperatorNode[] = []

export function MapMarkerLayer() {
const { chainId } = useStore()

const streamId = useStreamIdParam()

const nodesQuery = useOperatorNodesForStreamQuery(streamId || undefined)
const nodesQuery = useOperatorNodesForStreamQuery(streamId || undefined, chainId)

const nodes = nodesQuery.data || EmptyNodes

Expand Down
4 changes: 3 additions & 1 deletion src/components/NodeTopologyList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { TopologyList } from './TopologyList'
const EmptyNodes: OperatorNode[] = []

export function NodeTopologyList() {
const nodes = useOperatorNodesForStreamQuery(undefined).data || EmptyNodes
const { chainId } = useStore()

const nodes = useOperatorNodesForStreamQuery(undefined, chainId).data || EmptyNodes

const { selectedNode } = useStore()

Expand Down
7 changes: 4 additions & 3 deletions src/components/Stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ export const Stats = styled(UnstyledStats)`
position: relative;
`

function useStreamStatsQuery(streamId: string) {
const { chainId } = useStore()
function useStreamStatsQuery(streamId: string, chainId: number) {
return useQuery({
queryKey: ['useStreamStatsQuery', streamId, chainId],
queryFn: async () => {
Expand Down Expand Up @@ -285,7 +284,9 @@ const defaultStreamStats = {
}

export function StreamStats({ streamId }: StreamStatsProps) {
const { data: stats } = useStreamStatsQuery(streamId)
const { chainId } = useStore()

const { data: stats } = useStreamStatsQuery(streamId, chainId)

const { messagesPerSecond, peerCount, latency } = stats || defaultStreamStats

Expand Down
4 changes: 3 additions & 1 deletion src/components/StreamTopologyList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export function StreamTopologyList() {

const navigateToNode = useNavigateToNodeCallback()

const { data: nodes = [] } = useOperatorNodesForStreamQuery(streamId)
const { chainId } = useStore()

const { data: nodes = [] } = useOperatorNodesForStreamQuery(streamId, chainId)

const { selectedNode } = useStore()

Expand Down
18 changes: 17 additions & 1 deletion src/utils/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { config } from '@streamr/config'
export const POLYGON_CHAIN_ID = config.polygon.id
export const POLYGON_AMOY_CHAIN_ID = config.polygonAmoy.id
export const DEFAULT_CHAIN_ID = POLYGON_CHAIN_ID
export const SUPPORTED_CHAIN_IDS = [POLYGON_CHAIN_ID, POLYGON_AMOY_CHAIN_ID]
const SUPPORTED_CHAIN_IDS = [POLYGON_CHAIN_ID, POLYGON_AMOY_CHAIN_ID]

const INDEXER_URLS: Record<number, string> = {
[POLYGON_CHAIN_ID]: 'https://stream-metrics.streamr.network/api',
Expand All @@ -17,3 +17,19 @@ export function getIndexerUrl(chainId: number): string {
}
return uri
}

const CHAIN_ID_STORAGE_KEY = 'network-explorer-chain-id'

export function getPersistedChainId(): number {
const stored = localStorage.getItem(CHAIN_ID_STORAGE_KEY)

if (stored && SUPPORTED_CHAIN_IDS.includes(parseInt(stored, 10))) {
return parseInt(stored, 10)
}

return DEFAULT_CHAIN_ID
}

export function persistChainId(chainId: number): void {
localStorage.setItem(CHAIN_ID_STORAGE_KEY, chainId.toString())
}
8 changes: 6 additions & 2 deletions src/utils/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import { useOperatorNodesForStreamQuery } from './nodes'
export function useNodeConnections() {
const streamId = useStreamIdParam() || undefined

const { data: nodes } = useOperatorNodesForStreamQuery(streamId)
const { chainId } = useStore()

const { data: nodes } = useOperatorNodesForStreamQuery(streamId, chainId)

const { selectedNode } = useStore()

Expand Down Expand Up @@ -159,7 +161,9 @@ export function useAutoCenterNodeEffect() {

const streamId = useStreamIdParam()

const { data: nodes } = useOperatorNodesForStreamQuery(streamId || undefined)
const { chainId } = useStore()

const { data: nodes } = useOperatorNodesForStreamQuery(streamId || undefined, chainId)

const { nodeId: activeNodeId = null } = useParams<{ nodeId: string }>()

Expand Down
8 changes: 2 additions & 6 deletions src/utils/nodes.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { useIsFetching, useQuery } from '@tanstack/react-query'
import { MinuteMs } from '../consts'
import { getOperatorNodes } from '../getters'
import { useStore } from '../Store'

function getOperatorNodesForStreamQueryKey(streamId: string | undefined, chainId: number) {
return ['useOperatorNodesForStreamQuery', streamId || '', chainId]
}

export function useOperatorNodesForStreamQuery(streamId: string | undefined) {
const { chainId } = useStore()

export function useOperatorNodesForStreamQuery(streamId: string | undefined, chainId: number) {
return useQuery({
queryKey: getOperatorNodesForStreamQueryKey(streamId, chainId),
queryFn: () =>
Expand All @@ -21,8 +18,7 @@ export function useOperatorNodesForStreamQuery(streamId: string | undefined) {
})
}

export function useIsFetchingOperatorNodesForStream(streamId: string | undefined) {
const { chainId } = useStore()
export function useIsFetchingOperatorNodesForStream(streamId: string | undefined, chainId: number) {
const queryCount = useIsFetching({
exact: true,
queryKey: getOperatorNodesForStreamQueryKey(streamId, chainId),
Expand Down
9 changes: 7 additions & 2 deletions src/utils/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@ import { useIsFetchingOperatorNodesForStream, useOperatorNodesForStreamQuery } f
import { useIsFetchingLocationFeatures, useLocationFeaturesQuery } from './places'
import { useLimitedStreamsQuery } from './streams'
import { truncate } from './text'
import { useStore } from '../Store'

function getValidSearchPhrase(phrase: string) {
return phrase.length < 3 ? '' : phrase.toLowerCase()
}

export function useIsSearching(phrase: string) {
const isFetchingNodes = useIsFetchingOperatorNodesForStream(undefined)
const { chainId } = useStore()

const isFetchingNodes = useIsFetchingOperatorNodesForStream(undefined, chainId)

const isFetchingPlaces = useIsFetchingLocationFeatures(getValidSearchPhrase(phrase))

return isFetchingNodes || isFetchingPlaces
}

export function useSearch({ phrase: phraseParam = '' }) {
const nodesQuery = useOperatorNodesForStreamQuery(undefined)
const { chainId } = useStore()

const nodesQuery = useOperatorNodesForStreamQuery(undefined, chainId)

const phrase = useDebounce(getValidSearchPhrase(phraseParam), 250)

Expand Down
Loading

0 comments on commit 01e65df

Please sign in to comment.