Declaring function inside function in React - javascript

I just came across a React code and I'm not sure whether it's is a good way to do it or not. This is a sample implementation of that code.
class App extends React.Component {
renderMessage = () => {
function getMessage() {
return "Hello"
}
function getName() {
return "Vijay"
}
return (
<h1>{getMessage()} {getName()} !!!</h1>
)
}
render() {
return (
<div>
{this.renderMessage()}
</div>
)
}
}
Here we are calling a function renderMessage inside render. In renderMessage there are two inner functions which are called inside renderMessage only. My question now are:-
Is it a good approach to do? Won't it redeclare method getName and getMessage at every render call.
If I make getName and getMessage class methods and call them inside renderMessage would it be an improvment?
Thanks :)

Is it a good approach to do? Won't it redeclare method getName and getMessage at every render call
Definitely not a good approach. As JavaScript is either having functional or block or global scope.
Whatever you defining at this scope will be part of this scope only.In your case, these function getMessage and getName will be part of renderMessage which is functional scope.
At every call, new functions are getting defined instead reusing previously defined.
If I make getName and getMessage class methods and call them inside renderMessage would it be an improvement?
Depend.
If this function need an access to any component properties or method then you should place it inside the component or If this is only utility function then place it inside helper library separate from component.
Surely, this will make difference.

Is it a good approach to do? Won't it redeclare method getName and getMessage at every render call.
It will redecleare functions getName and getMessage at every render call. It's not great, but not terrible. This approach reduces bugs with rerendering - the function declaration is part of the render result. Although in your exact case it doesnt matter, as the functions will always return the same result and it doesnt depend on the state (although in that case it'd be more readable to just inline the strings)
If I make getName and getMessage class methods and call them inside renderMessage would it be an improvment?
It will make virtual life easier for the garbage collector. The chances are, once you start depending on global state, this will start to go wrong, e.g.:
class App extends React.Component {
getMessage => () {
return "Hello"
}
getName => () {
return this.props.name
}
renderMessage = () => {
someHttpAction().then(() => {
alert(getMessage() + ' ' + getName());
})
}
render() {
return (
<div onclick={this.renderMessage}>Say my name! (Hint, its {this.props.name})</div>
)
}
}
(Note that name is passed in as an argument to App)
When you render the first time, you might expect that, after clicking the text, you'll see an alert of "Hello Vijay". That's true, most of the time. But what happens if, after you click the text, you rerender with a different value for name, say Heisenberg, while someHttpAction promise still has not resolved? You might expect to see your name - Vijay, but actually you'll see the new value, "Hello Heisenberg". By declaring the function inline (as per your example), the function's scope is locked and you'll get the expected result "Hello Vijay".
Imagine a bit more complex scenario where you switch between multiple user profiles and the async messages start showing up on the wrong user...
While yes, we could pass name as an argument to getName, in reality, people think "its fine this time" or forget, and this is how bugs get introduced. Much less difficult to make the same mistake with inline functions. Unless this becomes a bottleneck, stick with the less errorprone approach.
Also, I suggest skimming through How Are Function Components Different from Classes?

It is possible, but it is not a good solution at all.
Yeah, it creates new function on each re-render, but it's not a case if you don't pass them as props.
The problem is that you can get a giant monster component with very ambiguous responsibilities in the nearest future.
Even more. It is bad in terms of performance. The bigger your component is, the bigger time it needs for re-render. And each smallest change will re-render the whole component, not only its part.
You should move renderMessage method to the new component for the sake of readability and scalability.
class App extends React.Component {
render() {
return (
<div>
<Message/>
</div>
)
}
}
class Message extends React.Component {
getMessage() {
return "Hello"
}
getName() {
return "Vijay"
}
render() {
return (
<h1>{this.getMessage()} {this.getName()} !!!</h1>
)
}
}

Related

Calling a method vs using a function to call a method

Suppose we have a method inside a class like this
class Blog extends Component {
postClicked = (id) => {
this.setState({selectedPostId: id})
}
render () {
const newPosts = this.state.posts.map(el => {
return <Post key={el.id}
title={el.title}
author={el.author}
onClick={this.postClicked(el.id)}/>
})
return
//something
{post}
}
}
}
Now, What is the difference between calling the handler like this
onClick={this.postClicked(el.id)} and onClick={() => this.postClicked(el.id)}
Would appreciate if someone can tell me the difference in general
after Ecmascript 6 javascript was introduced with is arrow function link
here ()==>{//code} is a similar as a function() or anonymous function
tell me if you find out what you want
The first option, "this.postClicked(el.id)", will actually call the method, "this.postClicked", with the "el.id" argument, each time the component renders (probably not what's intended).
The second option, "() => this.postClicked(el.id)", will only call the method, "this.postClicked", with the "el.id" argument, when "Post" is clicked.
Overall, if you can find a way to put the "el.id" argument into an "id" or "name" prop on the component
<Post id={el.id} />
then you can do:
<Post
id={el.id}
onClick={this.postClicked}
/>
this.postClicked = (event) => {
const { id } = event.target;
...
}
This last option avoids the use of an unnamed function. If you use an unnamed function, it will cause unnecessary re-renders. React cannot tell that an unnamed function is the same when it's checking whether or not it should re-render, by considering if the props of a component have changed. It considers the unnamed functions to be a new prop each time it checks, causing an unnecessary re-render each time.
Overall, it won't break your app, but it slows down performance slightly if you do it enough. It comes up especially if you start using React Motion (you'll really notice a difference there). It's best to avoid unnamed functions if possible.
you can read this blog it wil clear the things https://medium.com/#machnicki/handle-events-in-react-with-arrow-functions-ede88184bbb
Differences are,
First method is a wrong implementation and it wont give the intended result, where as second one will work.
In the first method you are making a function call, in second one you are assigning a function's signature to onClick.
It is like the combination of below two statements.
var variableName = function(){//some content};
onClick={variableName}
It looks like you question has already been answered. Just a side note though: remember that when assigning your method with an arrow function
onClick={ () => this.method() }
a new anonymous function is created on every re-render. So if the method doesn't need any arguments, it's better to reference the method directly (without parentheses so it's not invoked).
onClick={ this.method }
The first will call the function every time render is done.
The second will do what you want - call it onClick.

Why are stateless functions not supposed to have methods?

I have read in multiple places that stateless functions in React are not supposed to have inner functions. Why is it so, though it works?
const Foo = () => {
let bar = () => {
return <span>lorem ipsum</span>
}
return <div>{bar()}</div>
}
This works. But, why is this not supposed to be done?
N.B. This answer assumes that the use of the word "method" was incorrect, and that we are actually talking about an inner function, as in the example provided in the question.
A stateless component is defined as a function which returns something that can be rendered by React:
const MyStatelessComponent = function (props) {
// do whatever you want here
return something; // something must be render-able by React
}
To (re-)render the component, React calls the function, so it makes sense to perform expensive computations in advance and save their result outside of the function.
In your toy example, the function bar is declared once per render, and only used once. Let's assume that it was slightly more complicated and pass it a single parameter:
const Foo = () => {
let bar = text => {
return <span>{text}</span>
}
return <div>{bar("lorem ipsum")}</div>
}
By moving bar outside of the component, you don't need to create the function once per render, you just call the function that already exists:
const bar = text => {
return <span>{text}</span>
}
const Foo = () => {
return <div>{bar("lorem ipsum")}</div>
}
Now your component is ever-so-slightly more efficient, since is does less work every time it is called.
Also note that bar is almost the same as a stateless component now, and could easily be turned into one by making the function take a props object rather than a single string argument.
But the bottom line is that you can do whatever you want inside the stateless component. It just is worth bearing in mind that it will happen once per (re-)render.
While still valid code, as far as react is concerned, the above example is not a stateless component.
A stateless component is basically a shortcut to the render method of a stateful component (without the same life-cycle) and should "ideally" only return data, not define methods or actually manipulate or create additional data or functionality. With a stateful component, ideally, you do not define methods within the render method so none should be added in a stateless component.
By defining a method, function, or parameter inside of a stateless component but outside of the render method, you are essentially saying that there is a possibility of manipulation within the stateless component, which defeats the purpose.
Mind you, it's still valid code...but just not "react" ideal.
The function Foo is basically the render method of the React component. Therefore, it will be called everytime the component needs to be rendered. By declaring a local function inside it, it will create a new function everytime the component re-renders, which is bad.
Either declare the function outside or implement a stateful component instead.

Class properties for react lifecycle methods

Can I write React lifecycle methods as class properties?
I've been using class properties for a while as I like the fact that I no longer have to manually bind my methods, but I'd like to keep some consistency across my components and I'm wondering if there is any drawback on writing the React lifecycle methods as class properties
import React, { Component } from 'react';
class MyComponent extends Component {
render = () => {
return (
<div>Foo Bar</div>
);
}
}
export default MyComponent;
For example, is the context of this class property affected compared to the context in an equivalent method. Given that the render method in the above code is written as an arrow function, this concern seems relevant.
In a way, the true answer depends on your build pipeline and what the resulting Javascript output looks like. There are two primary possibilities:
Input Code
Let's start by saying you are writing the following before going through any sort of pipeline transformations (babel, typescript, etc):
class Test {
test = () => { console.log('test'); };
}
Output as class member variable.
In one possible world, your pipeline will also be outputting the test function as a member variable for the output class. In this case the output might look something like:
function Test() {
this.test = function() { console.log('test'); };
}
This means that whenever you write new Test() the test function is going to be recreated every single time.
Output as class prototype function
In the other major possibility, your pipeline could be recognizing this as a function property and escape it from the class instance to the prototype. In this case the output might look something like:
function Test() {
}
Test.prototype = {
test: function() { console.log('test'); }
}
This means that no matter how many times you call new Test() there will still be only one creation of the test function around in memory.
Desired behavior
Hopefully it's clear that you want your end result to have the function end up on the prototype object rather than being recreated on each class instance.
However, while you would want the function to not end up as a property, that doesn't necessarily mean you couldn't write it that way in your own code. As long as your build chain is making the correct transformations, you can write it any way you prefer.
Although, looking at the default babel settings (which your babeljs tag leads me to believe you are using) it does not make this transformation for you. You can see this in action here. On the left I've created one class with the function as a property and one class with the function as a class method. On the right hand side, where babel shows it's output, you can see that the class with the function as a property still has it being an instance-level property, meaning it will be recreated each time that class's constructor is called.
I did find this babel plugin, which seems like it might add this transformation in, but I've not used it for myself so I'm not positive.
In my experience, the most reason for writing a method as a class property is when the method will be passed as a callback, and you need it to always be bound to the instance. React lifecycle methods will always be called as a method, so there's no reason to bind them (and you incur a tiny memory penalty when you do). Where this makes a difference is when you're passing a function to a component as a callback (e.g. onClick or onChange).
Take this example:
class BrokenFoo extends React.Component {
handleClick() {
alert(this.props.message);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
)
}
}
The function represented by this.handleClick is not automatically bound to the component instance, so when the method tries to read the value of this.props it will throw a TypeError because this is not defined. Read this article if you're not familiar with this; the problem described in section 4.2 "Pitfall: extracting methods improperly" is essentially what's happening when you pass around a method without making sure it's bound correctly.
Here's the class, rewritten with the handler as a class property:
class HappyFoo extends React.Component {
handleClick = () => {
alert(this.props.message);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
)
}
}
Effectively, you can think of the handleClick definition in the second example as placing this code into the component's constructor (which is just about exactly the way Babel does it):
this.handleClick = () => {
alert(this.props.message);
}
This achieves the same thing as calling bind on the function (as described in the linked article) but does it a little differently. Because this function is defined in the constructor, the value of this in this.props.message is bound to the containing instance. What this means is that the function is now independent of the calling context; you can pass it around and it won't break.
The rule of thumb that I follow: by default, write methods as methods. This attaches the method to the prototype and will usually behave the way you'd expect. However, if the method is ever written without parentheses (i.e. you're passing the value and not calling it), then you likely want to make it a class property.

React JS binding callbacks

How can we practically prove the point, After Every render react creates new callback arrow function so it is a bad approach. See below code -
class DankButton extends React.Component {
render() {
// Bad Solution: An arrow function!
return <button onClick={() => this.handleClick()}>Click me!</button>
}
handleClick() {
this.logPhrase()
}
logPhrase() {
console.log('such gnawledge')
}
}
Also, how the below Arrow function class property function really works ?
class DankButton extends React.Component {
render() {
return <button onClick={this.handleClick}>Click me!</button>
}
// ES6 class property-arrow function!
handleClick = () => {
this.logPhrase();
}
logPhrase() {
console.log('such gnawledge')
}
}
I'm not sure i understand what you mean exactly by
How can we practically prove the point
As i understand from your question, i assume that you do realize that in the first example above, a new instance of a function is being created.
With that in mind, when you think about it, there are at least 2 issues when you create and pass a new instance of an object or function:
Maybe less important in most cases, you consume more memory on each
render.
More important (in my opinion) you can potentially interrupt the
Reconciliation and Diffing Algorithm of react by passing a new
prop on each render, this will cause a re-render of the child
component, hence performance issues can arise.
Arrow function class property function really works.
Sorry, Don't know how to prove the new instances of function when using bind, but I can do the latter.
console.log this in your arrow function, and compare it to one that is done as a regular function. Do not use bind at any point. The arrow function's this will be the component's context, while the function based one will be either window or undefined.

Closures in React

Is it ok use closures in react, for event handlers?
For example, i have some function and a lot of menu in navigation
and in navigation component i use something like this:
handleMenuClick(path) {
return () => router.goTo(path)
}
...
<MenuItem
handleTouchTap={this.handleMenuClick('/home')}
>
or i should prefer just arrow function?
<MenuItem
handleTouchTap={() => router.goTo('/home')}
>
first variant really make code cleaner, but i'm worried about performance with a large number of such elements
Both should be avoided.
While they'll both work, they both have the same weakness that they'll cause unnecessary renders because the function is being created dynamically, and will thus present as a different object.
Instead of either of those, you want to create your functions in a static way and then pass them in. For something like your MenuItem, it should just get the string for the path and then have the code to do the routing inside. If it needs the router, you should pass that in instead.
The function should then be a pre-bind-ed function (usually in the constructor) and just passed in.
export class MenuItem extends React.Component {
constructor() {
this.handleClick = () => this.props.router.go(this.props.path);
}
render() {
return (
<Button onClick={ this.handleClick }>Go to link</Button>
);
}
}
You can use an arrow function in the constructor. That way it isn't recreated every render function, and thus you avoid unnecessary renders. That pattern works well for single-line simple functions. For more complex functions, you can also create them as a separate function, then bind it in the constructor.
export class MenuItem extends React.Component {
handleClick() {
this.props.router.go(this.props.path);
}
constructor() {
this.handleClick = this.handleClick.bind(this);
}
render() { /* same as above */ }
}
The point of this is that the handler is the same function every time. If it was different (which both methods you describe above would be), then React would do unnecessary re-renders of the object because it would be a different function every time.
Here are two articles which go into more details:
https://ryanfunduk.com/articles/never-bind-in-render/
https://daveceddia.com/avoid-bind-when-passing-props/
when you define a new method inside a react component (Object) as we know functions are object in javascript.
let reactComponent={
addition: function(){ //some task ...},
render: function(){},
componentWillMount : function(){},
}
so, every new method should be bind with in the object using bind, but render() is already defined so we don't do
this.render = this.render.bind(this)
for each new function, except react lifecycle methods are needed to be added and hence, we call the object (constructor function) methods using this.method().

Categories

Resources