Skip to content

Commit

Permalink
Fix: Next 13 - useRouter() -> usePathName(), useParams() (#2478)
Browse files Browse the repository at this point in the history
* Fix: Next 13 - useRouter() -> usePathName(), useParams()

* Fix tests
  • Loading branch information
katspaugh committed Aug 31, 2023
1 parent a141aa1 commit d2d5dd2
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 52 deletions.
28 changes: 13 additions & 15 deletions src/components/tx-flow/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContext, type ReactElement, type ReactNode, useState, useEffect, useCallback } from 'react'
import TxModalDialog from '@/components/common/TxModalDialog'
import { useRouter } from 'next/router'
import { usePathname } from 'next/navigation'

const noop = () => {}

Expand All @@ -21,7 +21,8 @@ export const TxModalProvider = ({ children }: { children: ReactNode }): ReactEle
const [shouldWarn, setShouldWarn] = useState<boolean>(true)
const [, setOnClose] = useState<Parameters<TxModalContextType['setTxFlow']>[1]>(noop)
const [fullWidth, setFullWidth] = useState<boolean>(false)
const router = useRouter()
const pathname = usePathname()
const [, setLastPath] = useState<string>(pathname)

const handleModalClose = useCallback(() => {
setOnClose((prevOnClose) => {
Expand All @@ -38,13 +39,10 @@ export const TxModalProvider = ({ children }: { children: ReactNode }): ReactEle
}

const ok = confirm('Closing this window will discard your current progress.')
if (!ok) {
router.events.emit('routeChangeError')
throw 'routeChange aborted. This error can be safely ignored - https://github.com/zeit/next.js/issues/2476.'
if (ok) {
handleModalClose()
}

handleModalClose()
}, [shouldWarn, handleModalClose, router])
}, [shouldWarn, handleModalClose])

const setTxFlow = useCallback(
(txFlow: TxModalContextType['txFlow'], onClose?: () => void, shouldWarn?: boolean) => {
Expand All @@ -57,13 +55,13 @@ export const TxModalProvider = ({ children }: { children: ReactNode }): ReactEle

// Show the confirmation dialog if user navigates
useEffect(() => {
if (!txFlow) return

router.events.on('routeChangeStart', handleShowWarning)
return () => {
router.events.off('routeChangeStart', handleShowWarning)
}
}, [txFlow, handleShowWarning, router])
setLastPath((prev) => {
if (prev !== pathname && txFlow) {
handleShowWarning()
}
return pathname
})
}, [txFlow, handleShowWarning, pathname])

return (
<TxModalContext.Provider value={{ txFlow, setTxFlow, setFullWidth }}>
Expand Down
48 changes: 14 additions & 34 deletions src/hooks/__tests__/useChainId.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRouter } from 'next/router'
import { useParams } from 'next/navigation'
import useChainId from '@/hooks/useChainId'
import { useAppDispatch } from '@/store'
import { setLastChainId } from '@/store/sessionSlice'
Expand All @@ -9,18 +9,14 @@ import type { ConnectedWallet } from '@/services/onboard'
import type { ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'

// mock useRouter
jest.mock('next/router', () => ({
useRouter: jest.fn(() => ({
query: {},
})),
jest.mock('next/navigation', () => ({
useParams: jest.fn(() => ({})),
}))

describe('useChainId hook', () => {
// Reset mocks before each test
beforeEach(() => {
;(useRouter as any).mockImplementation(() => ({
query: {},
}))
;(useParams as any).mockImplementation(() => ({}))

Object.defineProperty(window, 'location', {
writable: true,
Expand All @@ -29,9 +25,7 @@ describe('useChainId hook', () => {
})

it('should read location.pathname if useRouter query.safe is empty', () => {
;(useRouter as any).mockImplementation(() => ({
query: {},
}))
;(useParams as any).mockImplementation(() => ({}))

Object.defineProperty(window, 'location', {
writable: true,
Expand All @@ -47,9 +41,7 @@ describe('useChainId hook', () => {
})

it('should read location.search if useRouter query.safe is empty', () => {
;(useRouter as any).mockImplementation(() => ({
query: {},
}))
;(useParams as any).mockImplementation(() => ({}))

Object.defineProperty(window, 'location', {
writable: true,
Expand All @@ -65,9 +57,7 @@ describe('useChainId hook', () => {
})

it('should read location.search if useRouter query.chain is empty', () => {
;(useRouter as any).mockImplementation(() => ({
query: {},
}))
;(useParams as any).mockImplementation(() => ({}))

Object.defineProperty(window, 'location', {
writable: true,
Expand All @@ -88,31 +78,25 @@ describe('useChainId hook', () => {
})

it('should return the chainId based on the chain query', () => {
;(useRouter as any).mockImplementation(() => ({
query: {
chain: 'gno',
},
;(useParams as any).mockImplementation(() => ({
chain: 'gno',
}))

const { result } = renderHook(() => useChainId())
expect(result.current).toBe('100')
})

it('should return the chainId from the safe address', () => {
;(useRouter as any).mockImplementation(() => ({
query: {
safe: 'matic:0x0000000000000000000000000000000000000000',
},
;(useParams as any).mockImplementation(() => ({
safe: 'matic:0x0000000000000000000000000000000000000000',
}))

const { result } = renderHook(() => useChainId())
expect(result.current).toBe('137')
})

it('should return the wallet chain id if no chain in the URL and it is present in the chain configs', () => {
;(useRouter as any).mockImplementation(() => ({
query: {},
}))
;(useParams as any).mockImplementation(() => ({}))

jest.spyOn(useWalletHook, 'default').mockImplementation(
() =>
Expand All @@ -130,9 +114,7 @@ describe('useChainId hook', () => {
})

it('should return the last used chain id if no chain in the URL and the connect wallet chain id is not present in the chain configs', () => {
;(useRouter as any).mockImplementation(() => ({
query: {},
}))
;(useParams as any).mockImplementation(() => ({}))

jest.spyOn(useWalletHook, 'default').mockImplementation(
() =>
Expand All @@ -150,9 +132,7 @@ describe('useChainId hook', () => {
})

it('should return the last used chain id if no wallet is connected and there is no chain in the URL', () => {
;(useRouter as any).mockImplementation(() => ({
query: {},
}))
;(useParams as any).mockImplementation(() => ({}))

renderHook(() => useAppDispatch()(setLastChainId('100')))

Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useChainId.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRouter } from 'next/router'
import { useParams } from 'next/navigation'
import { parse, type ParsedUrlQuery } from 'querystring'
import { IS_PRODUCTION } from '@/config/constants'
import chains from '@/config/chains'
Expand Down Expand Up @@ -31,11 +31,11 @@ const getLocationQuery = (): ParsedUrlQuery => {
}

export const useUrlChainId = (): string | undefined => {
const router = useRouter()
const queryParams = useParams()
const { configs } = useChains()

// Dynamic query params
const query = router && (router.query.safe || router.query.chain) ? router.query : getLocationQuery()
const query = queryParams && (queryParams.safe || queryParams.chain) ? queryParams : getLocationQuery()
const chain = query.chain?.toString() || ''
const safe = query.safe?.toString() || ''

Expand Down
5 changes: 5 additions & 0 deletions src/tests/pages/apps.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ jest.mock('@safe-global/safe-gateway-typescript-sdk', () => ({
getSafeApps: (chainId: string) => Promise.resolve(mockedSafeApps),
}))

jest.mock('next/navigation', () => ({
...jest.requireActual('next/navigation'),
useParams: jest.fn(() => ({ safe: 'matic:0x0000000000000000000000000000000000000000' })),
}))

describe('AppsPage', () => {
beforeEach(() => {
jest.restoreAllMocks()
Expand Down

0 comments on commit d2d5dd2

Please sign in to comment.