Guide to Resolving the "react/no-unescaped-entities" ESLint Error in Next.js

LightNode
Oleh LightNode ·

Introduction

Building rich user interfaces in Next.js often involves embedding text that contains special characters—such as quotes ("), apostrophes ('), and angle brackets (</>). ESLint's react/no-unescaped-entities rule prevents these characters from appearing unescaped in JSX, as they can lead to unexpected rendering or parsing issues. When triggered, you might see errors like:

no unescaped entities

./src/components/home/testimonials-section.tsx
74:17  Error: `"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.  react/no-unescaped-entities
74:53  Error: `"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`.  react/no-unescaped-entities
info  - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/app/api-reference/config/eslint#disabling-rules
// Example error in a Next.js component:
export default function Welcome() {
  return <h1>Welcome to John's Blog</h1>;
  //              ^ unescaped apostrophe here
}

Without addressing it, your CI/CD checks can fail, and collaborators may be confused by misleading lint warnings. This guide walks through why this error occurs and several robust fixes.

Understanding the Root Cause

JSX's Special Character Rules

JSX closely resembles HTML but is stricter with text parsing. Characters like < and > are parsed as element delimiters, while quotes and apostrophes denote attribute boundaries. Unescaped instances can break the AST:

<p>Use <strong>bold</strong> for emphasis.</p>
// The "<strong>" is interpreted as a nested element, not literal text.

Next.js's Default ESLint Configuration

Next.js ships with a built-in ESLint setup (@next/eslint-plugin-next) that extends the react and jsx-a11y presets. By default, the React preset includes:

"rules": {
  "react/no-unescaped-entities": "error"
}

As a result, any unescaped entity in your JSX triggers an error during development or build.

Why Rich-Text Projects Are More Affected

Projects with internationalization, markdown rendering, or heavy user-generated content tend to include many special characters. This increases the likelihood of unescaped entities and constant lint noise, slowing down development.

Disabling the Rule Globally

To suppress no-unescaped-entities across your entire project, update your .eslintrc.js:

module.exports = {
  extends: ["next", "next/core-web-vitals"],
  rules: {
    "react/no-unescaped-entities": "off",
  },
};

Adjusting ESLint via next.config.js

If you prefer to tweak ESLint only during builds, modify next.config.js:

module.exports = {
  eslint: {
    ignoreDuringBuilds: true, // skips all lint checks in production builds
  },
};

⚠️ This setting suppresses all ESLint errors on build, so use with caution.

Disabling on Specific Files or Components

To disable the rule in a single component or file, add an inline ESLint directive:

/* eslint-disable react/no-unescaped-entities */
export default function Caution() {
  return <p>Warning: Don't click that button!</p>;
}
/* eslint-enable react/no-unescaped-entities */

Considerations for TypeScript Projects

If you use a tsconfig.json path alias for lint overrides, ensure you reference the correct ESLint config:

// .eslintrc.js
module.exports = {
  parser: "@typescript-eslint/parser",
  extends: [
    "next",
    "next/core-web-vitals",
    "plugin:@typescript-eslint/recommended",
  ],
  rules: {
    "react/no-unescaped-entities": "off",
  },
};

Alternative Solution: Using HTML Entities

When you prefer to honor the lint rule and still render special characters correctly, replace them with HTML entities.

Common HTML Entities

Character Entity
Apostrophe (') &apos; or &#39;
Double quote (") &quot;
Less-than (<) &lt;
Greater-than (>) &gt;
Ampersand (&) &amp;

Correct Usage in JSX

export default function Quote() {
  return (
    <p>
      She said, &quot;Next.js is awesome!&quot; &amp; I couldn&apos;t agree more.
    </p>
  );
}

When to Apply This Method

  • Static copy: Hard-coded text in headers, footers, or marketing pages.
  • Localization files: JSON or YAML where entities persist through translation.
  • SEO-critical content: Ensures that the HTML source always encodes special symbols.

Other Practical Workarounds

JavaScript Expressions with Curly Braces

Wrap text in braces and use string literals to bypass JSX parsing:

export default function Ellipsis() {
  return <p>{'Wait for it...'}</p>;
}

Single Quotes Instead of Double Quotes

If your string contains double quotes, wrap it in single quotes or vice versa:

// Avoids unescaped double quotes in a string
<p title='She said "Hello" to me'>Greeting</p>

Leveraging React Fragments

For complex blocks with mixed markup, fragments help isolate text from tags:

export default function Mixed() {
  return (
    <>
      <p>Use <strong>React</strong> &amp; Next.js together!</p>
      <p>{'Enjoy your coding journey.'}</p>
    </>
  );
}

Summary & Reference Resources

Solution Pros Cons
Disable ESLint rule globally Quick fix, zero lint noise May hide genuine unescaped issues
HTML Entities Compliant, explicit encoding Verbose, harder to read
Inline ESLint disable comments Granular control Repetitive directives in code
JS Expressions / Quotes swap Flexible without disabling linting Less idiomatic JSX