I have a simple react ponent 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 ponent */
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 ponent */
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 ponent */
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 ponent */
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 ponentDidMount
or ponentDidUpdate
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?
I have a simple react ponent 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 ponent */
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 ponent */
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 ponent */
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 ponent */
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 ponentDidMount
or ponentDidUpdate
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 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. – TeaNyan Commented Jan 14, 2019 at 8:03
3 Answers
Reset to default 3The third method is certainly not ok. Adding the function inside the render
method will create a new doMath
function every time your ponent 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 ponent, I would suggest defining it in the ponent'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 ponent'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 ponent'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 ponent 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 ponent's instance
}
render() {
const {width, height} = this.state;
const result = MyComponent.doMath(width, height);
// render something
}
}
(C) And for pleteness, 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 ponent instance's internal state).
Now for (A), the method will be created for every instance of the ponent (maybe something to consider if you have many of them). You will have access to this
(so to the ponent'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.
The best way of these 3 is inside the class, since then other ponents can reuse that ponent with the math function. If you do that outside of the ponent this function is no longer tied to the ponent. However, in the future it is very likely that Class ponents will be obsolete and will no longer receive updates since Hooks are the new thing that make all the ponents 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!
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 ponent */
const { width, height } = attributes;
return (
{this.doMath()}
)
}
}