@@ -47,12 +47,18 @@ export const FeedList = ({
4747 const isSmartData = dataFeedType === "smartdata"
4848 const isUSGovernmentMacroeconomicData = dataFeedType === "usGovernmentMacroeconomicData"
4949
50- // Get network directly from URL
51- const networkFromURL =
52- typeof window !== "undefined" ? new URLSearchParams ( window . location . search ) . get ( "network" ) : null
50+ // Get network directly from URL with better SSR handling
51+ const getInitialNetwork = ( ) => {
52+ if ( typeof window === "undefined" ) return initialNetwork
53+ const params = new URLSearchParams ( window . location . search )
54+ const networkParam = params . get ( "network" )
55+ return networkParam || initialNetwork
56+ }
57+
58+ const networkFromURL = getInitialNetwork ( )
5359
5460 // If URL has a network param, use it directly
55- const effectiveInitialNetwork = networkFromURL || initialNetwork
61+ const effectiveInitialNetwork = networkFromURL
5662
5763 // Initialize state with the URL value
5864 const [ currentNetwork , setCurrentNetwork ] = useState ( effectiveInitialNetwork )
@@ -87,27 +93,46 @@ export const FeedList = ({
8793 }
8894 } , [ currentNetwork , isStreams ] )
8995
90- // Force initial sync with URL
96+ // Force initial sync with URL - handle hydration mismatches
9197 useEffect ( ( ) => {
92- // Get the latest network from URL
93- const latestNetworkFromURL = getNetworkFromURL ( )
94- if ( latestNetworkFromURL !== currentNetwork ) {
95- setCurrentNetwork ( latestNetworkFromURL )
98+ // Only run this effect on the client side after mount
99+ if ( typeof window !== "undefined" ) {
100+ const latestNetworkFromURL = getNetworkFromURL ( )
101+ if ( latestNetworkFromURL !== currentNetwork ) {
102+ setCurrentNetwork ( latestNetworkFromURL )
103+ }
96104 }
105+ } , [ ] ) // Run only once on mount
97106
98- // Force a redraw after a short delay
107+ // Additional sync for when window loads (fallback)
108+ useEffect ( ( ) => {
99109 if ( typeof window !== "undefined" ) {
100- // execute after the DOM is fully loaded
101- window . addEventListener ( "load" , ( ) => {
110+ const handleLoad = ( ) => {
102111 const networkFromURL = getNetworkFromURL ( )
103- setCurrentNetwork ( networkFromURL )
104- // Note: network button updates removed since we now use dropdown selector
105- } )
112+ if ( networkFromURL !== currentNetwork ) {
113+ setCurrentNetwork ( networkFromURL )
114+ }
115+ }
116+
117+ // If window is already loaded, run immediately
118+ if ( document . readyState === 'complete' ) {
119+ handleLoad ( )
120+ } else {
121+ window . addEventListener ( "load" , handleLoad )
122+ return ( ) => window . removeEventListener ( "load" , handleLoad )
123+ }
106124 }
107125 } , [ ] )
108126
109127 // Track the selected network type (mainnet/testnet)
110128 const [ selectedNetworkType , setSelectedNetworkType ] = useState < "mainnet" | "testnet" > ( "mainnet" )
129+
130+ // Track hydration to prevent SSR mismatch
131+ const [ isHydrated , setIsHydrated ] = useState ( false )
132+
133+ useEffect ( ( ) => {
134+ setIsHydrated ( true )
135+ } , [ ] )
111136
112137 // Regular query string states
113138 const [ searchValue , setSearchValue ] = useQueryString ( "search" , "" )
@@ -163,7 +188,32 @@ export const FeedList = ({
163188 ]
164189 const [ streamsChain ] = useState ( initialNetwork )
165190 const activeChain = isStreams ? streamsChain : currentNetwork
166- const chain = chains . find ( ( c ) => c . page === activeChain ) || chains [ 0 ]
191+
192+ // More robust chain finding - ensure we have a valid chain
193+ const chain = useMemo ( ( ) => {
194+ // During SSR, if we don't have an activeChain but we have a network param in the URL,
195+ // try to find the chain directly from the URL param to prevent hydration mismatch
196+ if ( ! activeChain ) {
197+ // Check if we have a network param that we can use directly
198+ if ( typeof window !== "undefined" ) {
199+ const urlParams = new URLSearchParams ( window . location . search )
200+ const networkParam = urlParams . get ( "network" )
201+ if ( networkParam ) {
202+ const foundFromUrl = chains . find ( ( c ) => c . page === networkParam )
203+ if ( foundFromUrl ) {
204+ return foundFromUrl
205+ }
206+ }
207+ }
208+ return chains [ 0 ] // fallback only if no activeChain
209+ }
210+
211+ const foundChain = chains . find ( ( c ) => c . page === activeChain )
212+ if ( ! foundChain ) {
213+ return chains [ 0 ]
214+ }
215+ return foundChain
216+ } , [ activeChain , chains ] )
167217 const chainMetadata = useGetChainMetadata ( chain , initialCache && initialCache [ chain . page ] )
168218 const wrapperRef = useRef ( null )
169219
@@ -644,16 +694,19 @@ export const FeedList = ({
644694 flexWrap : "nowrap"
645695 } }
646696 >
647- < ChainSelector
648- chains = { chains }
649- selectedChain = { chain }
650- currentNetwork = { currentNetwork }
651- onChainSelect = { handleNetworkSelect }
652- onNetworkTypeChange = { handleNetworkTypeChange }
653- dataFeedType = { dataFeedType }
654- availableNetworkTypes = { availableNetworkTypes }
655- selectedNetworkType = { selectedNetworkType }
656- />
697+ { isHydrated && (
698+ < ChainSelector
699+ key = { `chain-selector-${ chain . page } ` } // Force re-render when chain changes
700+ chains = { chains }
701+ selectedChain = { chain }
702+ currentNetwork = { currentNetwork }
703+ onChainSelect = { handleNetworkSelect }
704+ onNetworkTypeChange = { handleNetworkTypeChange }
705+ dataFeedType = { dataFeedType }
706+ availableNetworkTypes = { availableNetworkTypes }
707+ selectedNetworkType = { selectedNetworkType }
708+ />
709+ ) }
657710 </ div >
658711 </ >
659712 ) }
0 commit comments