Andree Christian
Andree Christian

Reputation: 477

JS Class that return a function

So i love this React thingy, and we have this so called 'stateless' functions to help us build a 'dumb' component. Now i want to create a class that produce a stateless function. Why you may ask, well i love the idea of inheritance and wanting to 'extend' my stateless function basic capability, said i want to add a helper function as a statics that binds to the function itself.

I ended up with this code

class Stateless {

  constructor() {
    return this.render.bind(this)
  }

  nanny() {
    // do something
  }

  render(props) {
    // yeay! a stateless function!
    // plus i can access nanny by using this.nanny()
  }
}

And when i extend it, i can see that the inheritance is working well. BUT, if then i initialize the class:

const stateless = new Stateless()

Why can't i access stateless.nanny even tho inside the render function i can see that this.nanny is accessible? Where does the nanny lives? Does it binded to the render function?

EG:

class Stateless {
  constructor() {
    return this.render.bind(this)
  }

  nanny() {
    console.log('foo')
    return true
  }

  render(props) {
    console.log(this.nanny()) // -> returns 'foo'
    return 'JSX'
    // this should return a JSX
  }
}

const stateless = new Stateless() // -> stateless IS a function

stateless()
// 'foo'
// true
// JSX

stateless.nanny
// undefined

While clearly inside render when i called this, there is nanny there. But when i refer it outside, the nanny is gone. I thought nanny should be a static property of the stateless, right?

Upvotes: 1

Views: 168

Answers (2)

Steve Holgado
Steve Holgado

Reputation: 12089

Your example should work if you remove this.render.bind(this) from your constructor.

It should also work, if you just remove return from the constructor:

constructor() {
  this.render.bind(this)
}

However, you might actually be looking to create a higher order component that can enhance the component that it wraps.

Your higher order component is a function that returns a class that renders the component that it passed to it:

import React from 'react'

function HigherOrderComponent(WrappedComponent) {

  return class Enhancer extends React.Component {
    constructor(props) {
      super(props)
    }

    exampleFunc() {
      // Code here
    }

    render() {
      return <WrappedComponent exampleprop={ this.exampleFunc } />
    }
  }

}

export default HigherOrderComponent

Then you can import HigherOrderComponent into your stateless dumb component file and wrap the export:

import React from 'react'
import HigherOrderComponent from './HigherOrderComponent'

const DumbComponent = (props) => {
  // Return JSX
  // You can use props.exampleprop
}

export default HigherOrderComponent(DumbComponent)

Here are some articles that you can read on higher order components: https://facebook.github.io/react/docs/higher-order-components.html https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e

Upvotes: 0

Amid
Amid

Reputation: 22382

If you are returning object from constructor - new will return that object instead of the instance of the class being constructed (more info).

Therefore line

const stateless = new Stateless()

will assign to stateless variable result of this.render.bind(this) - that is reference to method (function) of Stateless class, that is not an instance of Stateless. Therefore stateless.nanny makes no sense - as function render does not have such property defined. On the other hand calling bound render function directly - produce the expected result.

All in all - i strongly do not recommend you to return anything from constructor (unless you are dealing with some really weird requirements like controlling number of instances and such). It makes code hard to understand and maintain.

Upvotes: 1

Related Questions