oxc-project/oxc · warning · OxcDiagnostic

Disallow string literals in JSX attributes

Error message

Disallow string literals in JSX attributes

What it means

Attribute-case diagnostic of react/jsx-no-literals. It fires when noAttributeStrings is true (default false) and a JSX attribute is assigned a plain string literal, e.g. <input placeholder="Search" />. Like the children case, the goal is i18n and auditability: attribute values that users see should come from an expression (such as a translation function) rather than a hard-coded string. The help text says to replace the literal with a non-literal expression.

Source

Thrown at crates/oxc_linter/src/rules/react/jsx_no_literals.rs:35

use oxc_semantic::SymbolId;
use oxc_span::Span;
use oxc_str::CompactStr;

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
    utils::{default_true, is_react_component_name},
};

fn literal_text_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Disallow literal text as JSX children")
        .with_help("Wrap this text in a JSX expression container, such as a call to a translation function.")
        .with_label(span)
}

fn literal_attribute_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Disallow string literals in JSX attributes")
        .with_help("Replace this string literal with a non-literal expression, such as a call to a translation function.")
        .with_label(span)
}

fn restricted_attribute_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Disallow string literals on restricted JSX attributes")
        .with_help("This attribute is listed in `restrictedAttributes`; replace its string literal value with a non-literal expression.")
        .with_label(span)
}

/// The options shared between the top-level config and each `elementOverrides` entry.
#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct JsxNoLiteralsOptions {
    /// (default: false) - Enforces no string literals used as children, wrapped or unwrapped.
    no_strings: bool,
    /// An array of unique string values that would otherwise warn, but will be ignored.
    allowed_strings: Vec<CompactStr>,

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace the literal attribute value with an expression: placeholder={t('search.placeholder')}
  2. Whitelist genuinely local literals (symbols, constants) via allowedStrings
  3. Relax specific components with elementOverrides (e.g. allow a design-system Button's label)
  4. Turn the option off (noAttributeStrings defaults to false) if attribute strings are acceptable

Example fix

// before (noAttributeStrings: true)
<input placeholder="Search" />

// after
<input placeholder={t('search.placeholder')} />
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint -D react/jsx-no-literals src/  # with noAttributeStrings: true

Prevention

When it happens

Trigger: Config { "noAttributeStrings": true } plus any attribute with a StringLiteral value: <img alt="Logo"/>, <input placeholder="Email"/>, <Button label="Save"/>. Values in allowedStrings are exempt; elementOverrides can relax specific elements.

Common situations: Extending a no-literals i18n policy from children to attributes; UI libraries whose visible labels (aria-label, title, placeholder) must be translated; migrating from eslint-plugin-react configs where this was the noStrings+ignoreProps interplay — here it is a dedicated noAttributeStrings flag.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/9678b4654e3a2335. Report an issue: GitHub.