# Query params @tracked

**URL:** <https://discuss.emberjs.com/t/query-params-tracked/17467>\
**Category:** Uncategorized\
**Created:** [February 3, 2020, 9:26pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467 "2020-02-03T21:26:28Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![broerse](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/broerse/32/9497_2.png) [@broerse](https://discuss.emberjs.com/u/broerse)\
**Post date:** [February 3, 2020, 9:26pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/1 "2020-02-03T21:26:29Z")

</div>

I am switching the Bloggr example to Octane but was wondering if I need to add @tracked to [ember-cli-blog/posts.js at master · broerse/ember-cli-blog · GitHub](https://github.com/broerse/ember-cli-blog/blob/master/app/controllers/posts.js) for it seems to work perfect without it. Is there a @tracked query param rule of thumb?

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/chriskrycho/32/17763_2.png) [@chriskrycho](https://discuss.emberjs.com/u/chriskrycho)\
**Post date:** [February 4, 2020, 2:06am UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/2 "2020-02-04T02:06:56Z")

</div>

The rule of thumb is very roughly:

> Mark everything _you_ own as `@tracked`; trust the framework for things _it_ owns.

So, for example, query parameters (even though we set them up) are things the framework owns: it manages them based on the state of the URL. (They’re also two-way bound, which is the underlying reason why they work without being tracked). Likewise, you don’t mark Ember Data model properties as `@tracked`, because they’re configured for tracking via the other decorators `@attr`, `@belongsTo`, `@hasMany`.

On the other hand, if you’re defining a session service, _you_ own the data:

```js
import Service from '@ember/service';

export default class Session extends Service {
  @tracked user; // we own this!

  login(username: string, password: string) {
    fetch('https://example.com/login', { method: 'GET' })
      .then(data => data.json())
      .then(user => {
        this.user = user; // we set it here
      })
      .catch((e) => {
        alert("Whoops! Couldn't log in!");
        console.log(e);
      });
  }

  logout() {
    this.user = null;
  }
}

```

The same thing goes for components, _non_-framework-owned properties on controllers or models or Ember Data models, etc.

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [February 4, 2020, 1:57pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/3 "2020-02-04T13:57:01Z")

</div>

If that’s true then someone should update the Guides, as they show QPs being tracked:

> **[Query Parameters - Routing - Ember Guides](https://guides.emberjs.com/release/routing/query-params/)**
>
> Query parameters are optional key-value pairs that appear to the right of the ? in a URL. For example, the following URL has two query params, sort and page, with respective values ASC and 2: 
> 
> http://example.com/articles?sort=ASC&page=2  
> 
> Query...

And this is what it says on the page:

> Now we need to define a getter for our category-filtered array, which the `articles` template will render. For the getter to recompute when values change, `category` and `model` should be marked as tracked properties:

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/chriskrycho/32/17763_2.png) [@chriskrycho](https://discuss.emberjs.com/u/chriskrycho)\
**Post date:** [February 4, 2020, 2:14pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/4 "2020-02-04T14:14:03Z")

</div>

Interesting. Because of how tracking works, adding the annotation won’t break it, but there are definitely weird cases like this around query parameters specifically.

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [February 4, 2020, 2:45pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/5 "2020-02-04T14:45:20Z")

</div>

I’ve converted to Octane and, like you said in your initial response, non-tracked QPs worked fine for me.

---

<div class="post-metadata">

**Author:** ![broerse](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/broerse/32/9497_2.png) [@broerse](https://discuss.emberjs.com/u/broerse)\
**Post date:** [February 4, 2020, 6:53pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/6 "2020-02-04T18:53:05Z")

</div>

Thanks. It seems I don’t understand 100% why `@value={{query}}` does not need a @tracked anywhere. Even if I don’t make it a query param it still works fine. See:

> <https://github.com/broerse/ember-cli-blog/blob/master/app/components/blog-posts.hbs#L5>

This is also true for `page` and `perPage`. I would say the rule of thumb has not landed in my head but I am sure it will soon 😀

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/chriskrycho/32/17763_2.png) [@chriskrycho](https://discuss.emberjs.com/u/chriskrycho)\
**Post date:** [February 4, 2020, 7:10pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/7 "2020-02-04T19:10:24Z")

</div>

Arguments for Glimmer components are _always_ tracked!

---

<div class="post-metadata">

**Author:** ![balint](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/balint/32/12521_2.png) [@balint](https://discuss.emberjs.com/u/balint)\
**Post date:** [February 5, 2020, 11:21am UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/8 "2020-02-05T11:21:20Z")

</div>

As @chriskrycho says above, arguments of your Glimmer components are always tracked so I think that’s why `<Input @type="text" @value={{query}} ... />` works in your component.

I checked and you’re calling the component as follows:

`<BlogPosts @posts={{model}} @page={{page}} @perPage={{perPage}} @query={{query}} @createAction={{action "createPost"}}>{{outlet}}</BlogPosts>`

I’m not sure, though, as you have `@value={{query}}` and I’m not sure what `query` refers to here. For reasons of compatibility, it’s the same as writing `@value={{this.query}}` but afaict you don’t have a `query` property defined in the JS class of the `BlogPosts` component. That makes me think Ember still copies over component arguments to component properties and that’s why the above works at all. (It should be `@value={{@query}}`)

However, I think one of the best things in Octane is clarity in templates so I suggest to never have something without a `this` or `@` in your templates. If it starts with `this`, it must come from the backing class, if it starts with a `@`, it’s a component argument and should be passed in.

---

<div class="post-metadata">

**Author:** ![rwjblue](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/rwjblue/32/9411_2.png) [@rwjblue](https://discuss.emberjs.com/u/rwjblue)\
**Post date:** [February 5, 2020, 1:10pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/9 "2020-02-05T13:10:11Z")

</div>

> [@balint](#):
>
> That makes me think Ember still copies over component arguments to component properties and that’s why the above works at all. (It should be `@value={{@query}}` )

Just wanted to chime in here to confirm that this **does not happen**. When using `@glimmer/component` as your base class, the _only_ properties that will be set on the component instance by the framework are:

- `args`
- `isDestroying`
- `isDestroyed`
- the symbol used to power `getOwner(this)`

---

<div class="post-metadata">

**Author:** ![balint](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/balint/32/12521_2.png) [@balint](https://discuss.emberjs.com/u/balint)\
**Post date:** [February 5, 2020, 1:31pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/10 "2020-02-05T13:31:50Z")

</div>

Thanks, Rob, that’s great to know.

I realize now the component in question extends from `@ember/component` and that’s why it works.

> <https://github.com/broerse/ember-cli-blog/blob/master/app/components/blog-posts.js#L1>

@broerse You probably want to convert your components to Glimmer components to make them “Octane-friendly” .

---

<div class="post-metadata">

**Author:** ![broerse](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/broerse/32/9497_2.png) [@broerse](https://discuss.emberjs.com/u/broerse)\
**Post date:** [February 5, 2020, 5:45pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/11 "2020-02-05T17:45:06Z")

</div>

Thanks everybody. I will convert to Glimmer components too. The @tracked rule of thump seems to be more an `If - Then - Else schema` that has not landed with me yet.

---

<div class="post-metadata">

**Author:** ![broerse](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/broerse/32/9497_2.png) [@broerse](https://discuss.emberjs.com/u/broerse)\
**Post date:** [February 7, 2020, 11:32am UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/12 "2020-02-07T11:32:10Z")

</div>

I had to add @tracked on the controller to pass the tracked `queryParams` to Glimmer components like this: ([Switch to @tracked and @glimmer/component · broerse/ember-cli-blog@f0aefe3 · GitHub](https://github.com/broerse/ember-cli-blog/commit/f0aefe30b12844208436a70a395fd0b8febe09fc))

```auto
class QueryParamsObj {
  @tracked page = 1;
  @tracked perPage = 5;
  @tracked query = '';
}

export default class PostsController extends Controller {

  @alias ('queryParamsObj.page') page;
  @alias ('queryParamsObj.perPage') perPage;
  @alias ('queryParamsObj.query') query;

  queryParams= ["page", "perPage", "query"];
  queryParamsObj = new QueryParamsObj();

}

```

Still have to wrap my head around it but looks to me like @tracked Closure QueryParams.

Thanks for helping me get this figured out.

---

<div class="post-metadata">

**Author:** ![balint](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/balint/32/12521_2.png) [@balint](https://discuss.emberjs.com/u/balint)\
**Post date:** [February 7, 2020, 1:21pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/13 "2020-02-07T13:21:39Z")

</div>

So it didn’t work without defining them as in pre-Octane Ember?

```auto
export default class PostsController extends Controller {
  queryParams = ['page', 'perPage', 'query'];

  page = 1;
  perPage = 10;
  query = '';
  // (...)
}

```

---

<div class="post-metadata">

**Author:** ![broerse](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/broerse/32/9497_2.png) [@broerse](https://discuss.emberjs.com/u/broerse)\
**Post date:** [February 7, 2020, 1:52pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/14 "2020-02-07T13:52:48Z")

</div>

No it didn’t. @tracked is needed to add get & set to the query params . The Closure seems needed to pass the query parmas to `ember-cli-pagination` or `ember-cli-filter-by-query` etc

> <https://github.com/broerse/ember-cli-blog/blob/master/app/components/blog-posts.js>

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [February 7, 2020, 3:24pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/15 "2020-02-07T15:24:49Z")

</div>

The example @balint gave worked for me. This is what I have:

```
export default class Acts extends Controller {
queryParams = ['filterActs', 'searchActs'];

filterActs = '';
searchActs = '';
// (...)
}

```

---

<div class="post-metadata">

**Author:** ![broerse](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/broerse/32/9497_2.png) [@broerse](https://discuss.emberjs.com/u/broerse)\
**Post date:** [February 7, 2020, 5:46pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/16 "2020-02-07T17:46:39Z")

</div>

It only worked for me as long as I didn’t use `import Component from '@glimmer/component';`

Also `query` has no `get` and `set` defined on them needed for `ember-cli-filter-by-query`. Adding `@tracked` solved this for me.

You can see this on [GitHub - broerse/ember-cli-blog: Tom Dale's blog example updated for the Ember CLI](https://github.com/broerse/ember-cli-blog)

---

<div class="post-metadata">

**Author:** ![broerse](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/broerse/32/9497_2.png) [@broerse](https://discuss.emberjs.com/u/broerse)\
**Post date:** [February 7, 2020, 6:09pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/17 "2020-02-07T18:09:01Z")

</div>

It goes against @chriskrycho 's rule of thumps but without `@tracked` for example, this is not working.

```auto
  @action resetPage() {
    this.args.queryParamsObj.page = 1;
  }

```

It can be sometning I am doing wrong. Still learning `@tracked`

---

<div class="post-metadata">

**Author:** ![larryh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/larryh/32/16498_2.png) [@larryh](https://discuss.emberjs.com/u/larryh)\
**Post date:** [February 7, 2020, 7:42pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/18 "2020-02-07T19:42:41Z")

</div>

All of my imports are `import from '@glimmer/component'`

And I know what you mean about _still learning_… me too!

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/chriskrycho/32/17763_2.png) [@chriskrycho](https://discuss.emberjs.com/u/chriskrycho)\
**Post date:** [February 7, 2020, 9:06pm UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/19 "2020-02-07T21:06:54Z")

</div>

You should in general not be mutating state you don’t own. You _can_ do this kind of thing (though it’s not currently clear to me why this _would_ work if you were using `@tracked` on `queryParams` on the controller?) but in general it’s a bad plan to mutate the state remotely like this instead of letting the controller itself manage that state.

Another good rule of thumb here is: only the code which marks something as `@tracked` should _change_ it. (That’s not a hard and fast thing, as it’s idiomatic to change state of Ember Data models and `.save()` them, for example, but it’s a good rule of thumb.)

* * *

The reason I’m confused here is that `@tracked` does _not_ deeply track POJOs:

```nohighlight
import { @tracked } from '@glimmer/tracking';

export default class Example {
  @tracked pojo = { neat: true };
}

```

Here, `pojo` is tracked but `pojo.neat` is _not_. It would be very expensive to do that by default, and often you don’t want it. For these scenarios, you can do one of two things:

```nohighlight
import { @action } from '@ember/object';
import { @tracked } from '@glimmer/tracking';

export default class Example {
  @tracked pojo = { neat: true, cool: 'beans' };

  // mutate and "notify" by re-assigning itself
  @action mutateNeat(newValue) {
    this.pojo.neat = true;
    this.pojo = this.pojo;
  }

  // new object, "immutable functional update"
  @action immutableUpdateNeat(newValue) {
    this.pojo = { ...this.pojo, neat: newValue };
  }
}

```

Notably, though, this makes the QPs behavior… even weird.

@pzuraq, can you explain what’s happening here?

---

<div class="post-metadata">

**Author:** ![pzuraq](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/pzuraq/32/13754_2.png) [@pzuraq](https://discuss.emberjs.com/u/pzuraq)\
**Post date:** [February 8, 2020, 1:28am UTC](https://discuss.emberjs.com/t/query-params-tracked/17467/20 "2020-02-08T01:28:22Z")

</div>

Query params are a bit weird, because there are so many different ways to interact with them. The framework manages them using `get` and `set` internally, which is why generally, if you only interact with them using `transitionTo`, you’ll be fine.

However, if you do want to set them directly, you need to use `@tracked` like @broerse is suggesting, if I remember correctly. It’s debatable whether those properties are framework-owned or user-owned, but we figured that the hint of `@tracked` provided explicitly by the user would be better than magically tracking the properties automatically.

[Next page](https://discuss.emberjs.com/t/query-params-tracked/17467.md?page=2)
