Accessing a getter from a parameterized getter
Asked Answered
F

1

7

tl;dr

How to access other getters from a parameterized getter? Normally, you can use this.myGetter; but a parameterized getter is implemented as an arrow function, wherein this is undefined. What's the preferred way to handle this case in Pinia?


I'd like to create a parameterized getter (multiSum) in my Pinia store, which accesses another getter (sum).

Getters can be accessed via this, but that won't work from within an arrow function which is used to implemented a parameterized getter: multiSum crashes because this is undefined in the context of the nested arrow function.

getters: {
  sum: (state) => state.a + state.b,
  multiSum: (state) => (count) => this.sum * count // crash: this is undefined
}

In Vuex, parameterized getters can access other getters via a parameter instead of this, which also works in arrow functions. But afaik this API does not existing in Pinia.

I can work around this by capturing the store instance:

multiSum(state) {
  const store = this
  return (count) => store.sum * count
}

This works, but is pretty verbose. Is there a better (more framework-compliant) way to do this?

Fructuous answered 6/2, 2022 at 14:24 Comment(0)
E
10

this can be undefined inside arrow function because it's not interchangeable with regular function and gets a context from parent scope.

The usage of this and state is explained in details in the documentation. Either this or state can be used, but this has better Typescript and thus IDE support.

In the first snippet, state is already available in function scope, there is no need to access this:

multiSum: (state) => (count) => state.sum * count

In the second snippet, const store = this isn't needed because a store is already this.

multiSum() {
  return (count) => this.sum * count
}
Emissive answered 6/2, 2022 at 17:16 Comment(9)
Thanks! I was talking about the API you linked: in the docs it says "Access any other getter via this"; but this does not work with parameterized getters (pinia.vuejs.org/core-concepts/…) which are implemented as arrow functions. In the second snippet, this.sum fails because this inside the arrow function is undefined. Vuex provides a solution for this, by passing the getters object as optional argument to getters. (Will update my question.)Fructuous
It seems that you have problems with the fundamentals of JS here. multiSum from snippet 2 is regular function that has this context. Arrow higher order function doesn't have its own this and gets the nearest context, which is multiSum's. const store = this is redundant in the OP.Emissive
You are right in that the 2nd example wasn't correct. If should read instead: const store = this ; return (count) => store.sum * count -- I can't use this.sum inside the arrow function, that's why I have to capture the outer this in a variable. But once again: I know why this doesn't work; I'm not asking for help with JS arrow functions, but rather for a solution in Pinia.Fructuous
"I can't use this.sum inside the arrow function" - you can, if this is correct context. const store = this; return (count) => store.sum * count and return (count) => this.sum * count are absolutely the same when used inside multiSum() { regular (non-arrow) function.Emissive
They are not the same. In the one case I bind this in a variable outside the arrow function's scope, and can access it this way. Directly accessing this inside the arrow function does not work thoughFructuous
"Directly accessing this inside the arrow function does not work though" - can you provide a way to reproduce the problem? This isn't how arrow functions work, that's why I mentioned the problems with JS , the use of old recipe var self= this with arrows always indicates that there are some things about them that need to be studied. Check #28372482 . The reason why it didn't work in the OP as multiSum: (state) => (count) => this.sum * count is because both functions are arrows.Emissive
Aaah now I finally get what you mean. The reason why the 2nd example works is not because I captured this outside the arrow function, but rather because the arrow function is inside a non-arrow function. So I guess this is indeed the solution, plain and simple: just don't write the parameterized getter with 2 arrow functions. Thanks for your time!Fructuous
How with this method you can access other getters inside getter?Annitaanniversary
@Annitaanniversary Use regular function instead of an arrow and access the whole store as this, this is noted in the answer.Emissive

© 2022 - 2024 — McMap. All rights reserved.