简体   繁体   中英

How can I access constructor 'this' inside Ramda?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM