Ember对象状态泄漏错误:排序属性数组定义合规性咨询
Let's fix that ESLint error in your Ember controller! The issue here is that you've defined sortedProperties as a plain array directly on the controller's default properties, which violates the ember/avoid-leaking-state-in-ember-objects rule.
Why this happens
Ember shares default reference-type properties (like arrays or objects) across all instances of a class. That means if one instance modifies sortedProperties, every other instance of this controller would see that change too—this is called state leakage, and it's the exact problem the rule is trying to prevent. The rule only allows primitive values (strings, numbers, booleans, etc.) or functions as default properties because those don't carry shared state risks.
Solution 1: Use a function to return the array
Since functions are allowed as default properties, you can rewrite sortedProperties to return a new array each time an instance is created. This ensures every controller instance gets its own independent copy of the array:
import Controller from "@ember/controller"; import { computed } from "@ember/object"; export default Controller.extend({ filter: "", filterTodos: computed("arrangedContent", "filter", function() { var filter = this.get("filter"); var rx = new RegExp(filter, "gi"); var todos = this.model; return todos.filter(function(todo) { return todo.get("title").match(rx) || todo.get("body").match(rx); }); }), // Return a fresh array via a function to avoid shared state sortedProperties: () => ["date:asc"], sortedTodos: computed.sort("model", "sortedProperties") });
If you ever need access to the controller instance (this) in the property (you don't here, but just in case), use a regular function instead of an arrow function:
sortedProperties: function() { return ["date:asc"]; }.property(),
Solution 2: Initialize the property in the init method
Another reliable approach is to set sortedProperties inside the controller's init hook. This guarantees the array is created when the instance initializes, avoiding shared state:
import Controller from "@ember/controller"; import { computed } from "@ember/object"; export default Controller.extend({ filter: "", filterTodos: computed("arrangedContent", "filter", function() { var filter = this.get("filter"); var rx = new RegExp(filter, "gi"); var todos = this.model; return todos.filter(function(todo) { return todo.get("title").match(rx) || todo.get("body").match(rx); }); }), sortedTodos: computed.sort("model", "sortedProperties"), init() { this._super(...arguments); // Always call the parent class's init method first this.set("sortedProperties", ["date:asc"]); } });
Which solution to choose?
- Use Solution 1 for simple, static default values—it's concise and straightforward.
- Use Solution 2 if you need more complex initialization logic (like conditionally setting the sorted properties based on other data).
内容的提问来源于stack exchange,提问作者Abbas Ghaith

