oxc-project/oxc · warning · OxcDiagnostic

You should not use an arrow function to define a watcher.

Error message

You should not use an arrow function to define a watcher.

What it means

Diagnostic from oxlint's vue/no-arrow-functions-in-watch rule (since oxlint 1.39.0). It fires when an Options API `watch` option uses an arrow function as the handler. Arrow functions capture the enclosing `this` (module scope or undefined) instead of the component instance, so `this.foo` inside the watcher breaks at runtime. The help text suggests a regular function or method shorthand.

Source

Thrown at crates/oxc_linter/src/rules/vue/no_arrow_functions_in_watch.rs:17

use oxc_ast::{
    AstKind,
    ast::{
        CallExpression, ExportDefaultDeclarationKind, Expression, ObjectExpression,
        ObjectPropertyKind,
    },
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

use crate::{
    AstNode, context::LintContext, frameworks::FrameworkOptions, rule::Rule, utils::find_property,
};

fn no_arrow_functions_in_watch_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("You should not use an arrow function to define a watcher.")
        .with_help("Use a regular function or method shorthand instead of an arrow function.")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoArrowFunctionsInWatch;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// This rule disallows using arrow functions when defining a watcher.
    ///
    /// ### Why is this bad?
    ///
    /// Arrow functions bind `this` lexically, which means they don't have access to the Vue component instance.
    /// In Vue watchers, you often need access to `this` to interact with component data, methods, or other properties.
    /// Using regular functions or method shorthand ensures proper `this` binding.
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Use method shorthand: watch: { foo(val, oldVal) { this.doThing(val) } }
  2. Or reference a named method by string: watch: { foo: 'doThing' }
  3. Migrate the component to the Composition API watch()/watchEffect() where arrow closures are correct

Example fix

// before
watch: {
  query: (val) => { this.search(val) },
}
// after
watch: {
  query(val) { this.search(val) },
}
Defensive patterns

Strategy: validation

Validate before calling

# rough scan: arrow functions inside watch blocks
grep -rnA6 "watch: *{" --include='*.vue' src | grep "=>"

Prevention

When it happens

Trigger: A Vue options object (detected via find_property on the component options) has `watch: { foo: (val, oldVal) => { this.doThing() } }` — any arrow function as the immediate watch handler value.

Common situations: Developers converting methods or computed to watchers using arrow shorthand; class-property-style components where arrows are idiomatic everywhere except watch; copy-paste from Composition API examples into Options API code.

Related errors


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