Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is arrow syntax preferred over function declaration for functional React components?

I always see examples of functional React components defined with arrow function syntax:

const foo = () => (...);

export default foo;

Rather than the more traditional function declaration syntax:

export default function foo() {
  return ...;
}

Is there a reason to prefer the former over the latter?

like image 931
Philip Johnson Avatar asked Mar 15 '18 17:03

Philip Johnson


People also ask

Why are arrow functions preferred in React?

Arrow functions don't redefine the value of this within their function body. This makes it a lot easier to predict their behavior when passed as callbacks, and prevents bugs caused by use of this within callbacks.

Should I use arrow function for React component?

With the release of ES6 arrow function syntax, you now can use both regular JavaScript function and arrow function syntax when creating components. I would say that using the arrow function for React components is the right choice for most use cases.

Should I use arrow functions or functions?

The takeaway: Function expressions are best for object methods. Arrow functions are best for callbacks or methods like map, reduce, or forEach.

Why are arrow functions better JavaScript?

Arrow functions introduce concise body syntax, or implicit return. This allows the omission of the curly brackets and the return keyword. Implicit return is useful for creating succinct one-line operations in map , filter , and other common array methods.


3 Answers

I would say that this is a bit opinionated choice really. There are at least several reasons why I (personally) see arrow function use for a purely functional component as pretty bad practice. Here are those:

  1. Syntax abuse. When we define function component we don't need to pre-bind its context to a specific scope. The context (this) is going to be undefined anyway in the module namespace. The use of arrow functions is dictated here by pure aesthetics reasons like conciseness. But arrow functions as language feature has a very specific purpose for existence in the first place, and this is not coolness and conciseness.

  2. Error stack trace. Exceptions thrown in arrow function will be less descriptive because arrow function is anonymous by definition. This is not the huge problem probably since React project will most likely be configured with proper source maps support, but still stack trace will be a bit more clear if named function is used. As noted in comments this is not really an issue of the functional component, as the name will be the name of the variable basically.

  3. Less convenient logging. Consider this very typical pure function component style:

    const Header = ({ name, branding }) => (
      <header>
        ...
      </header>
    )
    

    In the function above it's impossible to throw in quick debugger statement or console.log. You will have to temporarily convert it to something like this

    const Header = function ({ name, branding }) { 
      console.log(name)
      return (
        <header>
          ...
        </header>
      )
    }
    

    This might be pretty annoying especially for bigger pure functional components.

That being said this is a very popular choice for many teams, also by default preferred by ESLint, so if you don't see the problem with it, then it is probably okay.

like image 157
dfsq Avatar answered Oct 25 '22 02:10

dfsq


Actually, there is no difference between them, I make a little project on the CodeSandBox and make two simple components, one of them is the Arrow component by using the arrow function:

import React from 'react';

const MyArrowComponent = () => (
  <main>
    <h2>Arrow</h2>
  </main>
);

export default MyArrowComponent;

And the other is the Declaration component by using function declaration:

import React from "react";

function MyFunctionComponent() {
    return (
        <main>
            <h2>Declaration</h2>
        </main>
    );
}

export default MyFunctionComponent;

Then I run the yarn build command and got the bundle like below:

(window.webpackJsonp = window.webpackJsonp || []).push([[0], {
  14: function (e, n, t) {
    "use strict";
    t.r(n);
    var a = t(0), r = t.n(a), l = t(2),
        c = t.n(l), u = t(3), i = t(4), o = t(6), m = t(5), E = t(7);
    var p = function () {
      return r.a.createElement("main", null, r.a.createElement("h2", null, "Declaration"))
    }, s = function () {
      return r.a.createElement("main", null, r.a.createElement("h2", null, "Arrow"))
    }, d = function (e) {
      function n() {
            return (
              Object(u.a)(this, n),
              Object(o.a)(this, Object(m.a)(n).apply(this, arguments))
      }
      return Object(E.a)(n, e), Object(i.a)(n, [{
        key: "render", value: function () {
          return r.a.createElement(
            'div',
            null,
            r.a.createElement('div', null, 'Hi'),
            r.a.createElement(p, null),
            r.a.createElement(s, null)
          );
        }
      }]), n
    }(r.a.Component);
    c.a.render(r.a.createElement(d, null), document.getElementById("root"))
  }, 8: function (e, n, t) {
    e.exports = t(14)
  }
}, [[8, 1, 2]]]);

Pay attention to the definition of the Arrow and the Declaration component:

var p = function () {
  return r.a.createElement("main", null, r.a.createElement("h2", null, "Declaration"))
}, s = function () {
  return r.a.createElement("main", null, r.a.createElement("h2", null, "Arrow"))
}

Both of them are defined in the same way, so definitely there is no difference between them and it is fully opinion based on developers' attitude to code readability and clean code, based on ESLint 5.x in our team, we choose the arrow function to define the functional components.

like image 12
AmerllicA Avatar answered Oct 25 '22 02:10

AmerllicA


Using Arrow function is way better than using a regular function not only because the syntax is clean and you will be able to write less code with the arrow function but also because of :

  1. Scope safety: when arrow functions are used consistently, everything is guaranteed to use the same thisObject as the root. If even a single standard function callback is mixed in with a bunch of arrow functions there's a chance the scope will become messed up.

  2. Compactness: Arrow functions are easier to read and write.

  3. Clarity: When almost everything is an arrow function, any regular function immediately sticks out for defining the scope. A developer can always look up the next-higher function statement to see what this object is.

For more details, you can take a look at these questions

When should I use Arrow functions in ECMAScript 6?

like image 5
Abslen Char Avatar answered Oct 25 '22 00:10

Abslen Char