73

I have a React component

export default class Archive extends React.Component { 
   ...
}

componentDidMount and onClick methods partially use the same code, except for slight change in parameters.

Is it possible to create a function inside the component class so it can be reused in the scope of the component?

Rizvan
  • 521
  • 1
  • 7
  • 20
Alexey
  • 3,607
  • 8
  • 34
  • 54

4 Answers4

124

You can create functions in react components. It is actually regular ES6 class which inherits from React.Component. Just be careful and bind it to the correct context in onClick event:

export default class Archive extends React.Component { 

    saySomething(something) {
        console.log(something);
    }

    handleClick(e) {
        this.saySomething("element clicked");
    }

    componentDidMount() {
        this.saySomething("component did mount");
    }

    render() {
        return <button onClick={this.handleClick.bind(this)} value="Click me" />;
    }
}
madox2
  • 49,493
  • 17
  • 99
  • 99
  • 1
    What if you want to do recursive call of a function? How do you call that within the function? – Norfeldt Mar 25 '17 at 17:36
  • 1
    @Norfeldt as simple as non-recursive call, just call the method/function `this.myMethod()` – madox2 Mar 26 '17 at 14:48
  • 1
    For me just `this.handleClick` works for me to invoke a custom function defined in my react component. What is this additional syntax `.bind(this)`? Why do we need it? – RBT Apr 29 '17 at 06:31
  • 3
    @RBT sure, it will invoke the function. The problem is that `this` inside the method will not be what you would expect. See more about it here http://stackoverflow.com/questions/33973648/react-this-is-undefined-inside-a-component-function – madox2 Apr 29 '17 at 12:00
  • 1
    In my implementation I get that `bind(this)` should not be used in a JSX component. any alternative to access the props from a custom function without binding `this` context? – Fed Feb 01 '18 at 12:36
  • 2
    @FedericoCapaldo bind the function only once, in constructor – madox2 Feb 01 '18 at 18:19
38

Another way:

export default class Archive extends React.Component { 

  saySomething = (something) => {
    console.log(something);
  }

  handleClick = (e) => {
    this.saySomething("element clicked");
  }

  componentDidMount() {
    this.saySomething("component did mount");
  }

  render() {
    return <button onClick={this.handleClick} value="Click me" />;
  }
}

In this format you don't need to use bind

yiwen
  • 1,057
  • 1
  • 12
  • 17
  • Can I try to access these local functions, from a different component?? I mean can we export such a function, actually I am getting error – Partha Paul Oct 19 '20 at 14:50
  • 1
    I wouldn't recommend that. I would just create a function in another file, and call the function in both (or more) places. In my example above, I would add a `saySomething.js` and export `saySomething` there. Then in both of components you `import saySomething` and then call the function. The advantage of this approach is `saySomething` can be unit tested in separation and you have 2 independent components that just so happen using some same code instead of tangle them together – yiwen Oct 20 '20 at 15:27
  • It's not even working for me this. I am getting _saySomething is not a function_ on the very declaration line. I need to use old way of ES5 `function() { ... }` or declare the function in another file. – nickornotto Oct 10 '22 at 21:23
13

You can try this.

// Author: Hannad Rehman Sat Jun 03 2017 12:59:09 GMT+0530 (India Standard Time)

import React from 'react';
import RippleButton from '../../Components/RippleButton/rippleButton.jsx';

class HtmlComponents extends React.Component {

    constructor(props){
        super(props);
        this.rippleClickFunction=this.rippleClickFunction.bind(this);
    }

    rippleClickFunction(){
        //do stuff. 
        // foo==bar
    }

    render() {
      return (
         <article>
             <h1>React Components</h1>
             <RippleButton onClick={this.rippleClickFunction}/>
         </article>
      );
   }
}

export default HtmlComponents;

Yhe only concern is you have to bind the context to the function

Adam Azad
  • 11,171
  • 5
  • 29
  • 70
hannad rehman
  • 4,133
  • 3
  • 33
  • 55
4

With React Functional way

import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import Button from "@material-ui/core/Button";

const App = () => {
  const saySomething = (something) => {
    console.log(something);
  };
  useEffect(() => {
    saySomething("from useEffect");
  });
  const handleClick = (e) => {
    saySomething("element clicked");
  };
  return (
    <Button variant="contained" color="primary" onClick={handleClick}>
      Hello World
    </Button>
  );
};

ReactDOM.render(<App />, document.querySelector("#app"));

https://codesandbox.io/s/currying-meadow-gm9g0

Shaik Md N Rasool
  • 484
  • 1
  • 5
  • 13
  • 1
    Is this actually ok? Or is there a performance overhead? I kinda assumed you'd have to declare the methods outside of the component function – Dylan Watson Jul 03 '21 at 01:07
  • 1
    I think you'd need to use useCallback to stop the function being redefined everytime. https://stackoverflow.com/questions/46138145/functions-in-stateless-components – Dylan Watson Jul 03 '21 at 01:10