Skip to content

Commit

Permalink
feat(codemod): add codemod that renames the Hydrate component usage…
Browse files Browse the repository at this point in the history
…s to `HydrationBoundary` usages
  • Loading branch information
balazsmatepetro committed Jul 21, 2023
1 parent 77bd2c3 commit 01e3419
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react'
import {
Hydrate,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

export default function MyApp({ Component, pageProps }) {
const [queryClient] = React.useState(() => new QueryClient())

return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
</Hydrate>
<ReactQueryDevtools />
</QueryClientProvider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react'
import {
HydrationBoundary,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

export default function MyApp({ Component, pageProps }) {
const [queryClient] = React.useState(() => new QueryClient())

return (
(<QueryClientProvider client={queryClient}>
<HydrationBoundary state={pageProps.dehydratedState}>
<Component {...pageProps} />
</HydrationBoundary>
<ReactQueryDevtools />
</QueryClientProvider>)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react'
import {
Hydrate as RenamedHydrate,
QueryClient as RenamedQueryClient,
QueryClientProvider as RenamedQueryClientProvider,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

export default function MyApp({ Component, pageProps }) {
const [queryClient] = React.useState(() => new RenamedQueryClient())

return (
<RenamedQueryClientProvider client={queryClient}>
<RenamedHydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
</RenamedHydrate>
<ReactQueryDevtools />
</RenamedQueryClientProvider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react'
import {
HydrationBoundary as RenamedHydrate,
QueryClient as RenamedQueryClient,
QueryClientProvider as RenamedQueryClientProvider,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

export default function MyApp({ Component, pageProps }) {
const [queryClient] = React.useState(() => new RenamedQueryClient())

return (
<RenamedQueryClientProvider client={queryClient}>
<RenamedHydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
</RenamedHydrate>
<ReactQueryDevtools />
</RenamedQueryClientProvider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const defineTest = require('jscodeshift/dist/testUtils').defineTest

defineTest(__dirname, 'rename-hydrate', null, 'default-import', {
parser: 'tsx',
})

defineTest(__dirname, 'rename-hydrate', null, 'named-import', {
parser: 'tsx',
})
55 changes: 55 additions & 0 deletions packages/codemods/src/v5/rename-hydrate/rename-hydrate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module.exports = (file, api) => {
const jscodeshift = api.jscodeshift
const root = jscodeshift(file.source)

const importSpecifiers = root
.find(jscodeshift.ImportDeclaration, {
source: {
value: '@tanstack/react-query',
},
})
.find(jscodeshift.ImportSpecifier, {
imported: {
name: 'Hydrate',
},
})

if (importSpecifiers.length > 0) {
const names = {
searched: 'Hydrate', // By default, we want to replace the `Hydrate` usages.
target: 'HydrationBoundary', // We want to replace them with `HydrationBoundary`.
}

importSpecifiers.replaceWith(({ node: mutableNode }) => {
/**
* When the local and imported names match which means the code doesn't contain import aliases, we need
* to replace only the import specifier.
* @type {boolean}
*/
const usesDefaultImport =
mutableNode.local.name === mutableNode.imported.name

if (!usesDefaultImport) {
// If the code uses import aliases, we must re-use the alias.
names.searched = mutableNode.local.name
names.target = mutableNode.local.name
}

// Override the import specifier.
mutableNode.imported.name = 'HydrationBoundary'

return mutableNode
})

root
.findJSXElements(names.searched)
.replaceWith(({ node: mutableNode }) => {
mutableNode.openingElement.name.name = names.target
mutableNode.closingElement.name.name = names.target

return mutableNode
})
}

return root.toSource({ quote: 'single', lineTerminator: '\n' })
}

0 comments on commit 01e3419

Please sign in to comment.