Skip to content

Commit

Permalink
refactor, better detection
Browse files Browse the repository at this point in the history
  • Loading branch information
balazsorban44 committed Oct 3, 2022
1 parent bbbe7e1 commit af5b591
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 24 deletions.
27 changes: 20 additions & 7 deletions packages/eslint-plugin-next/src/rules/date-hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,31 @@ export = defineRule({
return {
JSXExpressionContainer(node) {
const n = node as JSXExpressionContainer
if (n.expression.type !== 'CallExpression') return
else if (n.expression.callee.type !== 'MemberExpression') return
else if (n.expression.callee.object.type !== 'NewExpression') return
else if (n.expression.callee.object.callee.type !== 'Identifier') return
else if (n.expression.callee.object.callee.name !== 'Date') return
const { type } = n.expression

if (
type !== 'CallExpression' ||
n.expression.callee.type !== 'MemberExpression' ||
n.expression.callee.object.type !== 'NewExpression' ||
n.expression.callee.object.callee.type !== 'Identifier' ||
n.expression.callee.object.callee.name !== 'Date'
) {
return
}

const parent = context
.getAncestors()
.reverse()[0] as unknown as JSXElement

const attributes = new NodeAttributes(parent.openingElement)
const suppressed = attributes.has('suppressHydrationWarning')
const propertyName = (n.expression.callee.property as any)
.name as string
if (propertyName.match(/UTC|ISO/)) return

const attr = new NodeAttributes(parent.openingElement)

const suppressed =
attr.has('suppressHydrationWarning') &&
attr.value('suppressHydrationWarning') !== false

if (suppressed) return

Expand Down
44 changes: 27 additions & 17 deletions test/unit/eslint-plugin-next/date-hydration.test.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
import rule from '@next/eslint-plugin-next/dist/rules/date-hydration'
import { ruleTester } from './utils'

const invalidCommon = {
filename: 'pages/index.tsx',
errors: [
{
message:
'Rendering `Date` directly can cause a hydration mismatch. See https://nextjs.org/docs/messages/date-hydration',
type: 'JSXExpressionContainer',
},
],
}

ruleTester.run('date-hydration', rule, {
valid: [
`export default function Page() {
return <p suppressHydrationWarning={true}>{new Date().toLocaleString()}</p>
}`,
`export default function Page() {
return <p >{format(new Date())}</p>
}`,
`export default () => <p suppressHydrationWarning={true}>{new Date().toLocaleString()}</p>`,
`export default () => <p suppressHydrationWarning>{new Date().toLocaleString()}</p>`,
`export default () => <p>{format(new Date())}</p>`,
`export default () => <p>{new Date().toISOString()}</p>`,
`export default () => <p>{new Date().toUTCString()}</p>`,
],
invalid: [
{
code: `export default function Page() {
return <p>{new Date().toLocaleString()}</p>
}`,
filename: 'pages/index.js',
errors: [
{
message:
'Rendering `Date` directly can cause a hydration mismatch. See https://nextjs.org/docs/messages/date-hydration',
type: 'JSXExpressionContainer',
},
],
code: `export default () => <p>{new Date().toLocaleString()}</p>`,
...invalidCommon,
},
{
code: `export default () => <p>{new Date().getTime()}</p>`,
...invalidCommon,
},
{
code: `export default () =>
<p suppressHydrationWarning={false}>{new Date().toLocaleString()}</p>`,
...invalidCommon,
},
],
})

0 comments on commit af5b591

Please sign in to comment.