9

before someone as this duplicate to this question Can you write nested functions in JavaScript?

I am wondering if we can do something like this?

const toolbar = (props) => {
let sidedrawer = false;

  showSideDrawer = () => {
    sidedrawer = !sidedrawer
  }

  return (
    <header className={Classes.Toolbar} purchasingHandlerClose={this.showSideDrawer}>
//Something here
    </header>
  )
}
export default toolbar;

More precisely, something like this in functional component

 showSideDrawer = () => {
        sidedrawer = !sidedrawer
      }

and then calling it like this

  <header className={Classes.Toolbar} purchasingHandlerClose={this.showSideDrawer}>

Now, I know we can do this stateful component or class but then again in JS, Class is just syntactical sugar (still trying to figure out the meaning of the phrase), so how can we implement something like this in stateless or functional component?

Alwaysblue
  • 9,948
  • 38
  • 121
  • 210

2 Answers2

11

You can write a function within a stateless functional component, however function component don't have a this variable and in order to call the function you would simply write

const toolbar = (props) => {
  let sidedrawer = false;

  const showSideDrawer = () => {
    sidedrawer = !sidedrawer
  }

  return (
    <header className={Classes.Toolbar} purchasingHandlerClose={showSideDrawer}>
//Something here
    </header>
  )
}
export default toolbar;

However one pitfall of the above is that everytime the toolbar component is rendered sidedrawer is initiased to false and hence the showSideDrawer doesn't work as expected. You can however move the sidedrawer variable outside of functional scope and it will work

let sidedrawer = false;
const toolbar = (props) => {

  const showSideDrawer = () => {
    sidedrawer = !sidedrawer
  }

  return (
    <header className={Classes.Toolbar} purchasingHandlerClose={showSideDrawer}>
//Something here
    </header>
  )
}
export default toolbar;

However in this case too, the showSideDrawer function is also created everytime toolbar is render which isn't the right way to do and hence if you want to have such a functionality its always advisable to write a class component instead of a functional component because functional components are supposed to be pure..

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 2
    Thanks for amazing answer, Just one thing, what is the problem if `showSideDrawer`created everytime toolbar is render? Besides Performance? – Alwaysblue Jun 13 '18 at 08:04
  • This is gross. Why would you create your own state like this? You claim you want a stateless component but you do not have one. – jens Jun 13 '18 at 08:19
  • 2
    @jens, we shouldn't create a stateless component like this. Its just an example – Shubham Khatri Jun 13 '18 at 08:57
  • I figured you knew that, but I was concerned @KuchiBhi might not get that from the answer. – jens Jun 13 '18 at 09:18
  • @jens, ohh perhaps I haven't highlighted the part where I have suggested that using class component is much better for such use cases – Shubham Khatri Jun 13 '18 at 09:19
  • Yeah it doesn’t make it clear that this is a stateful component now even though its function based. Even though it’s bold you left out the explicit why. – jens Jun 13 '18 at 09:20
  • Thank you for all your contributions to the community Shubham. – jens Jun 13 '18 at 09:29
  • 1
    @ShubhamKhatri what do you mean by **functional components are supposed to be pure**? – Alwaysblue Jun 13 '18 at 10:51
  • by pure, I mean that it doens't have any sideeffects, it takes the input and return an output is purely dependent on the input. Any time you call the function with same input it returns you the same output – Shubham Khatri Jun 13 '18 at 11:36
3

You can write nested function as this is concept of JavaScript. But as Reactjs, it re-render only if props or state change. So if you update any local variable or this.something, It will not reflect on UI. It can show on UI only if parent state or props changes and React thing about this compenent should update.

If you want to update UI based on variable, state or props should update. So either you have to pass to props and handle state in parent or you have to create stateful component.

You might be trying to get something different, please share you scenario. Might be we can find a proper way based on situation.

Kishan Mundha
  • 2,989
  • 18
  • 26
  • `const toolbar = (props) => { let sidedrawer = false; showSideDrawer = () => { sidedrawer = !sidedrawer } }` will this be a valid syntax? and if yes, how do we call it? – Alwaysblue Jun 13 '18 at 07:39