1

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?

Andree Christian
  • 437
  • 4
  • 16
  • If you can give a more concrete case, it would be easy for all of us to help you in a better way. – Rajesh Sep 08 '17 at 07:52
  • I'll elaborate by making an example – Andree Christian Sep 08 '17 at 07:53
  • Try `console.log(stateless)`. – ceving Sep 08 '17 at 08:09
  • @ceving https://babeljs.io/repl/#?babili=false&browsers=&build=&builtIns=false&code_lz=FDDGBsEMGdoAgDIFMDmB7OBvYBIaAXSfAS1DnwE8AHJOAXjgHJxU1GQdQ0A7AgJwCuofGj4AKAJRZcOPknwC-3cgAti0AHRzuAEyR8NAI2K6x-NdAm4AvhwAKfNFQAq1JPAbY43n5ABccACMwD5wtiE-Kkjg4GiS0qHeXLxoLBqxKGKMUTFsVolwcgpKquoA3BHe4bJIuvrxXonJ0KlI6WiZ5uoaObGS-YlFispdmg5OrjTQMgD0M6qOAO5w3EjLAKJ8juIABgAiGNxo-HAC0LQAJJijGpQ01nA6xHLC4BQAhDtWOLbhAG6QPhwSBoWgMVbLZDoSQVMA8FppDJiEFIfoVZqtdqZFESdHwzFIlE9aKxCRAA&debug=false&circleciRepo=&evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-0&prettier=false&targets=&version=6.26.0 – Andree Christian Sep 08 '17 at 08:11

2 Answers2

1

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.

Amid
  • 21,508
  • 5
  • 57
  • 54
  • Hi Amid, thanks for answering! Now I *intentionally* return this.render because that is what I want. I want `stateless` to be just a function and no more. Since stateless component is a function. Now, can I assume that by doing `new Stateless()` in this way, I have create an instance that is nowhere to be referenced yet part of it still live in `stateless` ? Coz definitely I can access `this.nanny()` inside the `stateless()` – Andree Christian Sep 08 '17 at 10:53
  • 1
    Exactly - you create instance of Stateless that is not referenced anywhere except from within `render` because you have bound it in constructor. Therefore inside `render` call - `this` is still instance of the Stateless component, otherwise inaccessible outside. – Amid Sep 08 '17 at 11:04
  • Cool! An automated closure :D haha.. anyway, do you know any method to kinda *reattach* the `nanny` to the `stateless` from inside the class? I mean, I don't wanna reattach it once the `new` invoked. Thanks – Andree Christian Sep 08 '17 at 11:09
  • It gets misleading really fast. In your case you want to reattach `nanny` to `stateless` that is actually reference to `render` method. I do not think its what you really want. Maybe you need pure javascript function object with attached properties instead of class with such a weird constructor. – Amid Sep 08 '17 at 11:20
  • Yes, kind of: https://stackoverflow.com/questions/8588563/adding-custom-properties-to-a-function – Amid Sep 08 '17 at 11:25
  • Maybe, I am exploring the possibilities here. I just want to be able to call it from outside like a static property of a function. But if that's not possible I wouldn't mind – Andree Christian Sep 08 '17 at 11:25
0

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

Steve Holgado
  • 11,508
  • 3
  • 24
  • 32