3

I have a simple react component to which I want to add a simple math function named doMath that uses property values.

class MyClass extends Component {
    constructor( props ) {
        super( ...arguments );
    }

    render() {
        const { attributes } = this.props; /* attributes passed from parent component */
        const { width, height } = attributes;

        return (
           /* render something using the width and height values */
        )
    }
}

I can add the doMath function in the following ways...

Inside the class:

class MyClass extends Component {
    constructor( props ) {
        super( ...arguments );
    }

    doMath() {
       const { width, height } = this.props.attributes;
       const result = 100 / (width / height);
       return result;
    }

    render() {
        const { attributes } = this.props; /* attributes passed from parent component */
        const { width, height } = attributes;

        return (
           doMath();
        )
    }
}

Outside the class as a const:

const doMath = (width, height) {
  const result = 100 / (width / height);
  return result;
}

class MyClass extends Component {
    constructor( props ) {
        super( ...arguments );
    }

    render() {
        const { attributes } = this.props; /* attributes passed from parent component */
        const { width, height } = attributes;

        return (
           doMath(width, height);
        )
    }
}

Inside render as a const:

class MyClass extends Component {
    constructor( props ) {
        super( ...arguments );
    }

    render() {
        const { attributes } = this.props; /* attributes passed from parent component */
        const { width, height } = attributes;

        const doMath = (width, height) {
           const result = 100 / (width / height);
           return result;
        }

        return (
           doMath(width, height);
        )
    }
}

Seems like I can also add it to componentDidMount or componentDidUpdate

From what I understood it is bad practice to add it in render() but it seems to work everywhere. What is the best practice in this situation?

1
  • 1
    If you are using it only in this class, it should remain inside the class as class method, but if you're gonna need that function for other classes too, you can keep it in some API file and export it. Commented Jan 14, 2019 at 8:03

3 Answers 3

3

The third method is certainly not ok. Adding the function inside the render method will create a new doMath function every time your component re-renders, and that's not a performant way of doing things.

If you know for sure you're going to use the doMath function only for this particular component, I would suggest defining it in the component's module without exporting it. So I would opt for the second way.

If this function only depends on width and height, then it's good to have it outside the component's class. Otherwise, if you feel like it might depend on more of the state, you could put it inside the class so you are not forced to pass the component's state around.

Conclusion: depending of how much data you are going to pass to the doMath function you can either create it inside the class or outside of it; but never in the render method.


EDIT: Something I forgot to mention is using a static method. Basically if you're not setting the method static, it will be created for every instance of your component and will be able to use other class members:

(A) If the method's not static:

class MyComponent extends React.Component {
  /* private */ doMath() {
    // You have access to this particular instance and its state
    const {width, height} = this.state; 
  }
}

(B) If the method is static:

class MyComponent extends React.Component {
  /* private */ static doMath(width, height) {
    // do something with them
    // no access to state or the component's instance
  }

  render() {
    const {width, height} = this.state;

    const result = MyComponent.doMath(width, height);

    // render something
  }
}

(C) And for completeness, let's also define the function outside the class:

function doMath(width, height) {
  // do magic
  return result;
}

class MyComponent extends React.Component {
  render() {
    const {width, height} = this.state;
    const result = doMath(width, height);

    // render something
    // use result
  }
}

// emphasize export
module.exports = MyComponent;

Comparison

When using something like TypeScript, methods (B) and (C) are basically giving the same result: you can isolate functionality by specifing the static method private. However, when using JavaScript, I prefer (C) because if I do

const MyComponent = require('/path/to/MyComponent');
MyComponent.doMath(); // undefined

I cannot use the doMath function because I shouldn't. With these two methods, you need to pass the required data to the function/method as parameters (i.e. you don't have access to the component instance's internal state).

Now for (A), the method will be created for every instance of the component (maybe something to consider if you have many of them). You will have access to this (so to the component's internal state) and you don't have to pass anything as parameter, which may be convenient if you are unsure how much data the method needs.

I hope you'll be able to draw a conclusion from this explanation.

Sign up to request clarification or add additional context in comments.

8 Comments

I usually add one component per file so it will be ok to add it to component. I have not considered adding more components in one file.
What concerns me always is isolating functionality. So I wouldn't want any other module in the codebase to be able to access the doMath method since it's only for internal usage. If you used TypeScript, you would be able to specify the method as private and you'd get an error if you tried accessing it from somewhere else. However, if you're writing JavaScript only, it's a good idea (IMO) to put it outside of the class and not export it.
That is a good point! As far as personal preference would you use arrow functions and pass variables doMath = (properties) => {} or a normal function and grab the properties inside doMath() { const { properties } = this.props; ?
@CyberJunkie see my edit. Please tell me if there's anything unclear.
@CyberJunkie oh that was just to provide an example of usage. it has nothing with neither performance nor personal taste. PS: if you found my answer useful, please do not forget to mark it accepted
|
3

The best way of these 3 is inside the class, since then other components can reuse that component with the math function. If you do that outside of the component this function is no longer tied to the component. However, in the future it is very likely that Class components will be obsolete and will no longer receive updates since Hooks are the new thing that make all the components have state. If function was stateless before it will be stateful in the hooks version and you should read about it it is a great thing!

1 Comment

Woah! Hooks change everything.
0

Just put it inside the class and call it by {this.doMath()} in the render method

class MyClass extends Component {
    constructor( props ) {
        super( ...arguments );
    }

    doMath() {
       const { width, height } = this.props.attributes;
       const result = 100 / (width / height);
       return result;
    }

    render() {
        const { attributes } = this.props; /* attributes passed from parent component */
        const { width, height } = attributes;

        return (
           {this.doMath()}
        )
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.