{"record":{"id":"611fa89862904b88","repo":"oxc-project/oxc","slug":"the-deprecated-lifecycle-hook-is-deprecated-u","errorCode":null,"errorMessage":"The `{deprecated}` lifecycle hook is deprecated. Use `{replacement}` instead.","messagePattern":"The `(.+?)` lifecycle hook is deprecated\\. Use `(.+?)` instead\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/vue/no_deprecated_destroyed_lifecycle.rs","lineNumber":20,"sourceCode":"    AstKind,\n    ast::{\n        CallExpression, ExportDefaultDeclarationKind, Expression, ObjectExpression,\n        ObjectPropertyKind, PropertyKey,\n    },\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\nuse rustc_hash::FxHashSet;\n\nuse crate::{context::LintContext, rule::Rule};\n\nfn no_deprecated_destroyed_lifecycle_diagnostic(\n    span: Span,\n    deprecated: &str,\n    replacement: &str,\n) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\n        \"The `{deprecated}` lifecycle hook is deprecated. Use `{replacement}` instead.\"\n    ))\n    .with_help(format!(\"Replace `{deprecated}` with `{replacement}`.\"))\n    .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoDeprecatedDestroyedLifecycle;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow using deprecated `destroyed` and `beforeDestroy` lifecycle hooks in Vue.js 3.0.0+.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// In Vue.js 3.0.0+, the `destroyed` and `beforeDestroy` lifecycle hooks have been renamed\n    /// to `unmounted` and `beforeUnmount` respectively. Using the old names is deprecated and","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/vue/no_deprecated_destroyed_lifecycle.rs#L2-L38","documentation":"Diagnostic from oxlint's vue/no-deprecated-destroyed-lifecycle rule (since oxlint 1.35.0). It fires when a component uses the Vue 2 lifecycle hooks `destroyed` or `beforeDestroy`: in Vue 3 they were renamed to `unmounted` and `beforeUnmount`, and the old names are silently never invoked, so cleanup code simply stops running (leaks, lingering listeners). The message and help text interpolate the deprecated hook and its replacement.","triggerScenarios":"A component options object declares a `destroyed` or `beforeDestroy` property (tracked in a FxHashSet of deprecated hook names with their replacements).","commonSituations":"Components migrated from Vue 2 that keep teardown in destroyed(); nothing crashes, but timers, event listeners, and observers are never cleaned up, producing slow memory leaks that only show up in long sessions.","solutions":["Rename beforeDestroy to beforeUnmount","Rename destroyed to unmounted","Add this rule to the migration lint set so every renamed hook is caught in one pass"],"exampleFix":"// before\nbeforeDestroy() { this.unsubscribe() },\ndestroyed() { this.teardown() },\n// after\nbeforeUnmount() { this.unsubscribe() },\nunmounted() { this.teardown() },","handlingStrategy":"validation","validationCode":"# find Vue 2 destroy lifecycle hooks\ngrep -rnE \"\\b(beforeDestroy|destroyed)\\s*\\(\" --include='*.vue' src","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use beforeUnmount/unmounted names from the start of any Vue 3 project","After renaming, test teardown paths (route away, unmount) to confirm cleanup actually runs"],"tags":["vue","oxlint","lint","lifecycle","vue3","migration","deprecated","memory-leak"],"backgroundTag":"vue-2-to-3-migration","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}