jsx-no-literals
jsx-no-literals rule
Keywords: React, JSX, string literals, i18n, internationalization, translation, ESLint rule, LLM-optimized
Prevents string literals directly in JSX to encourage internationalization and consistent text management. This rule is part of eslint-plugin-react-features and provides LLM-optimized error messages.
Quick Summary
| Aspect | Details |
|---|---|
| Severity | Warning (i18n best practice) |
| Auto-Fix | ❌ No (requires extraction to translation keys) |
| Category | React |
| ESLint MCP | ✅ Optimized for ESLint MCP integration |
| Best For | Internationalized apps, consistent text management |
Rule Details
Why This Matters
| Issue | Impact | Solution |
|---|---|---|
| 🌍 i18n | Can't translate hardcoded text | Use translation keys |
| 📝 Consistency | Duplicate strings across app | Centralize text management |
| 🔄 Updates | Hard to update text globally | Single source of truth |
| 🧪 Testing | Brittle text-based tests | Use data-testid instead |
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
noStrings | boolean | true | Disallow string literals in JSX |
allowedStrings | string[] | [] | Strings that are allowed (e.g., symbols) |
ignoreProps | boolean | true | Allow strings in prop values |
Examples
❌ Incorrect
// Hardcoded text in JSX
function Welcome() {
return <h1>Welcome to our app!</h1>;
}
// Multiple hardcoded strings
function Button() {
return (
<button>
Click here to continue
</button>
);
}
// Text in complex components
function Card() {
return (
<div>
<h2>Product Title</h2>
<p>This is a description.</p>
</div>
);
}✅ Correct
// Using translation function
import { t } from './i18n';
function Welcome() {
return <h1>{t('welcome.title')}</h1>;
}
// Using constants
const BUTTON_TEXT = 'Click here to continue';
function Button() {
return <button>{BUTTON_TEXT}</button>;
}
// Using react-intl
import { FormattedMessage } from 'react-intl';
function Card() {
return (
<div>
<h2><FormattedMessage id="card.title" /></h2>
<p><FormattedMessage id="card.description" /></p>
</div>
);
}
// Props are allowed by default
<input placeholder="Search..." />Configuration Examples
Basic Usage
{
rules: {
'react-features/jsx-no-literals': 'warn'
}
}Allow Common Symbols
{
rules: {
'react-features/jsx-no-literals': ['error', {
noStrings: true,
allowedStrings: ['©', '•', '|', '-', '→', '←'],
ignoreProps: true
}]
}
}Strict Mode (Including Props)
{
rules: {
'react-features/jsx-no-literals': ['error', {
noStrings: true,
allowedStrings: [],
ignoreProps: false
}]
}
}Disabled for Whitespace
{
rules: {
'react-features/jsx-no-literals': ['warn', {
noStrings: true,
allowedStrings: [' ', '\n'],
ignoreProps: true
}]
}
}Migration Strategy
Step 1: Extract to Constants
// Before
<button>Submit Form</button>
// After
const SUBMIT_TEXT = 'Submit Form';
<button>{SUBMIT_TEXT}</button>Step 2: Move to Translation File
// translations/en.json
{
"form.submit": "Submit Form"
}
// Component
import { t } from './i18n';
<button>{t('form.submit')}</button>Step 3: Support Multiple Languages
// translations/en.json
{ "form.submit": "Submit Form" }
// translations/es.json
{ "form.submit": "Enviar Formulario" }
// translations/ja.json
{ "form.submit": "フォームを送信" }Related Rules
no-unescaped-entities- Escape special charactersjsx-max-depth- Limit JSX nesting
Further Reading
- React Internationalization - React docs
- react-intl - Popular i18n library
- i18next - Another i18n solution
- ESLint MCP Setup - Enable AI assistant integration
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Dynamic Variable References
Why: Static analysis cannot trace values stored in variables or passed through function parameters.
// ❌ NOT DETECTED - Prop from variable
const propValue = computedValue;
<Component prop={propValue} /> // Computation not analyzedMitigation: Implement runtime validation and review code manually. Consider using TypeScript branded types for validated inputs.
Wrapped or Aliased Functions
Why: Custom wrapper functions or aliased methods are not recognized by the rule.
// ❌ NOT DETECTED - Custom wrapper
function myWrapper(data) {
return internalApi(data); // Wrapper not analyzed
}
myWrapper(unsafeInput);Mitigation: Apply this rule's principles to wrapper function implementations. Avoid aliasing security-sensitive functions.
Imported Values
Why: When values come from imports, the rule cannot analyze their origin or construction.
// ❌ NOT DETECTED - Value from import
import { getValue } from './helpers';
processValue(getValue()); // Cross-file not trackedMitigation: Ensure imported values follow the same constraints. Use TypeScript for type safety.