Whenever I try to access any this
inside Ramda Compose function ( R.compose
) I get undefined
, maybe it's because this
is 'binded' to the Ramda Compose function.
How can I make this
access something that is initiated in the Class
constructor?
this.state
is undefined inside getContent
in the code below:
export default class FaqStore {
constructor() {
this.state = new FaqState()
this.getParents()
}
getContent = R.concat(this.state.parents, R.prop('content'))
getParents = FaqService.getParents().then(this.getContent)
The answer from Felix Kling is excellent. I want to add a little more context from Ramda, though.
Ramda (disclaimer: I'm one of the authors) is about functional programming. It tries to do two things: to make it easier for Javascript developers to move towards more standard FP practices, and to make it easier for users of FP languages to work with Javascript. There is no emphasis at all on interoperating with object-oriented styles of coding.
At one point Ramda did try to ensure that certain of its functions did maintain the this
context, which would allow them to be used as OOP methods. But we are dropping this focus entirely; it had always been speculative, without any requests at all for it, and when we accidentally broke it for some functions, we had no complaints at all. There seems to be little reason for it. Meanwhile it complicates our implementation and hurts performance. So as we find the need to rewrite functions, we're no longer trying to ensure that this is maintained.
This makes sense. Some people see Ramda as an alternative to Underscore or lodash, but that has always seemed skewed to us. Those libraries introduce some FP concepts, but they're designed to work in multi-paradigm environments, equally happy with imperative, OOP, or FP codebases. Ramda is different, designed to work well only in functional systems. It's built entirely around the notion of building systems by composing pure functions.
For these reasons, on top of everything Felix said, there's no real reason to expect that a Ramda function will maintain your this
context.
It seems like you are using the public class fields proposals. Properties created this way are evaluated before the constructor itself is executed (step 8 and 11).
Ie your code is equivalent to
export default class FaqStore {
constructor() {
this.getContent = R.concat(this.state.parents, R.prop('content'))
this.getParents = FaqService.getParents().then(this.getContent)
this.state = new FaqState()
this.getParents()
}
}
This clearly shows that you are trying to access this.state
before it was initialized.
Possible Solution
Don't use the proposal and set the properties directly in the constructor, after you initialized this.state
:
export default class FaqStore {
constructor() {
this.state = new FaqState()
this.getContent = R.concat(this.state.parents, R.prop('content'))
this.getParents = FaqService.getParents().then(this.getContent)
this.getParents()
}
}
However , there is still an issue: The value assigned to getParents
is a promise. You cannot call a promise ( this.getParents()
). Maybe what you really want is to assign a function to getParents
:
this.getParents = () => FaqService.getParents().then(this.getContent)
And maybe R.concat
doesn't return a function either, in which case this.getContent
cannot be called either. In that case, what you actually want is
export default class FaqStore {
constructor() {
this.state = new FaqState()
this.getParents()
}
getContent = () => R.concat(this.state.parents, R.prop('content'))
getParents = () => FaqService.getParents().then(this.getContent)
}
ie assign functions to getContent
and getParents
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.