122

I'm new to both ES6 and React and I keep seeing arrow functions. Why is it that some arrow functions use curly braces after the fat arrow and some use parentheses? For example:

const foo = (params) => (
    <span>
        <p>Content</p>
    </span>
);

vs.

const handleBar = (e) => {
    e.preventDefault();
    dispatch('logout');
};
1

9 Answers 9

198

The parenthesis are returning a single value, the curly braces are executing multiple lines of code.

Your example looks confusing because it's using JSX which looks like multiple "lines" but really just gets compiled to a single "element."

Here are some more examples that all do the same thing:

const a = (who) => "hello " + who + "!";
const b = (who) => ("hello " + who + "!");
const c = (who) => (
  "hello " + who + "!"
);
const d = (who) => (
  "hello "
    + who
    + "!"
);
const e = (who) => {
  return "hello " + who + "!";
}; 

You will also often see parenthesis around object literals because that's a way to avoid the parser treating it as a code block:

const x = () => {} // Does nothing
const y = () => ({}) // returns an object
6
  • 3
    Awesome, thank you. That also helps me understand some other errors I've been getting. I'll accept that as correct once I can. Thanks david
    – dkimot
    Commented Sep 22, 2016 at 3:58
  • 3
    One can also use curly braces to prevent an arrow function from returning a value -- or to make it obvious that a single line arrow function shouldn't return anything. Check my answer for an example (couldn't format it nicely as a comment).
    – GrayedFox
    Commented Mar 15, 2018 at 1:38
  • 2
    I get GrayedFox idea, however, why did somebody even implement this? Seems kinda tricky to me as maybe in a special case you're not sure if it should be () or {}
    – Advena
    Commented Aug 1, 2018 at 9:33
  • so I can use "return" only with curly braces and not with parenthesis ? If YES why is that ?
    – vikramvi
    Commented Apr 7, 2021 at 10:49
  • 1
    @vikramvi Because the parentheses mean the function will return the result of the single statement inside them, i.e. const x = () => (x) is equal to const x = () => {return x} . You can always use the curly braces, but you can use the parentheses instead for returning a value from a single statement concisely. Commented Jun 29, 2021 at 18:57
39

One can also use curly braces to prevent a single line arrow function from returning a value -- or to make it obvious to the next developer that a single line arrow function shouldn't, in this case, be returning anything.

For example:

const myFunc = (stuff) => { someArray.push(stuff) }
const otherFunc = (stuff) => someArray.push(stuff)

console.log(myFunc())    // --> logs undefined
console.log(otherFunc()) // --> logs result of push which is new array length
1
  • this is a good example that tripped me up before, wondering why my array was not being updated by push, when it would be missing the return before someArray in the the myFunc. Commented Apr 26, 2023 at 8:06
20

Parenthesis are used in an arrow function to return an object.

() => ({ name: 'YourName' })  // This will return an object

That is equivalent to

() => {
   return { name : 'YourName' }
}
0
14

Actually in a briefcase when somebody uses braces in an arrow function declaration, it is equal to below:

const arrow = number => number + 1;

|||

const arrow = (number) => number + 1;

|||    

const arrow = (number) => ( number + 1 );

|||

const arrow = (number) => { return number + 1 };
4
  • so I can use "return" only with curly braces and not with parenthesis ? If YES why is that ?
    – vikramvi
    Commented Apr 7, 2021 at 10:50
  • @vikramvi, see, it is just a simple syntax, when your function doesn't have anything inside execution context so just make it simple with less code, => without curly braces means return, simple to read, easy to understand, less in bundle size. see, it is pure beauty.
    – AmerllicA
    Commented Apr 7, 2021 at 12:02
  • Thanks for info, I understood that; but my question was; it is possible to use "return" with ( ) as well ?
    – vikramvi
    Commented Apr 7, 2021 at 12:24
  • 1
    @vikramvi, Obviously no.
    – AmerllicA
    Commented Apr 7, 2021 at 13:21
12

Parenthesis has an implicit return statement while curly braces you need an explicit return statement

1
  • That's fundamental for arrow functions, why is it not in the top answers? Commented May 18 at 13:30
6

If you use curly braces after the arrow to define the function body, you have to use the 'return' keyword to return something.

For example:

const myFun1 = (x) => {
    return x;
}; // It will return x

const myFun2 = (x) => {
    x;
}; // It will return nothing

If you use the parenthesis, you don't need to mention the 'return' keyword.

For example:

const myFunc1 = (x) => x; // It will return x

const myFunc2 = (x) => (x); // It will also return x
2

In your first example, the right-hand side of the arrow function shows a single expression that is enclosed by a grouping operator:

const foo = (params) => (
  <span>
    <p>Content</p>
  </span>
);

A similar comparable case would be the following:

const foo = (params) => (<span><p>Content</p></span>);

A distinction, in the above cases using single expressions, is that the right-hand side is the returned value of the function.

On the other hand, if you use curly braces, JavaScript will understand that as a statement:

const foo = (params) => {} // this is not an object being returned, it's just an empty statement 

Therefore, using statement is a good start for you to have code in it, multiple lines, and it will require the use of "return" if the function is intended to return value:

const foo = (params) => {
    let value = 1; 
    return value;
}

In case you wanted to return an empty object in the shortest form:

const foo = (params) => ({}) 

See tests

0

To answer a duplicate post(question posted here), just for reference for others:

  var func = x => x * x;                  
    // concise body syntax, implied "return"

    var func = (x, y) => { return x + y; }; 
    // with block body, explicit "return" needed

For reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Function_body

Also note: If you are returning an object literal as the result from a fat arrow function, then you must enclose the object in parentheses, e.g., myFunc = () => ({ data: "hello"}). You will receive an error if you omit the parentheses because the build tools will assume that the curly braces of the object literal are the start and end of a function body.

0

Every function has 2 aspects.

First of them is that each one, not just the arrow functions, has an execution context (a block scope) in which the variables are created and used.

In other words, inside the curly braces { ... } of the function, what is declared and assigned there, stays there and is not visible to the outside functions / or variables.

For example, when writing something as

let x = 100;

function doSomething() {
  let x = 50;
  console.log(x);
}

doSomething();     // 50
console.log(x);    // 100

both values are displayed in console (instead of 'x from outside just being replaced by x from inside the function').

You see that despite of let not usually allowing other variable x to be declared again (with the same name x), in this case, because the second x is declared and initialized inside the { ... }, it does not alter the outside one, which also happens because after the function doSomething is called, the x from inside of it is created, assigned, printed in console and then destroyed (deleted from the memory). So that process happens every time we call that function by running doSomething() .

So this is the first aspect to take into consideration when understanding the functions: they execute then forget the values created by the code inside their curly braces.

Because of it, it's easier to understand their second aspect -- as functions cannot just work isolated from the others, they need to also send data to the others, so they have some 'reporting aspect' used to externalize some part of the results computed inside their curly braces, which is exactly why the return statement exists.

Return exists in each function, even in the console.log or alert(), even in doSomething(), but in these cases where we didn't explicitly set something for it, it is always 'return undefined'.

Therefore it isn't necessary to write it, but instead know that where you don't return something specific, the function itself will do it for you by returning undefined.

When you write (or use) a function meant just to execute something, it will also return undefined. Always.

You can check that thing with every function which (apparently) has no declared return:

let x = alert(100);
console.log(x); // undefined

let y = doSomething(); // console prints 50
console.log(y);        // 50, then undefined --- 2 lines

console.log(alert('Hello')); // undefined

console.log(console.log('Okay')); // Okay , then undefined

Why is that?

Because alert() which is a method of global object window (in browser) (so it is actually window.alert() ) and also console.log() (which is the same with window.console.log() , too), execute something (printing in an alert box or in the console whatever is in between the () AND THEN return undefined).

Now, coming back to the arrow functions, they are not just some new way of notation for writing the functions but they also have some specific features.

First, if you only have a parameter between the () in an arrow function, you can write it without the parentheses.

Second, if inside the curly braces there's a single statement, you can omit as well the curly braces.

Third one, if the single statement is a return statement, you can omit the word return.

Somehow, using these we could transform many usual functions into arrow functions if needed:

function doSomething() {let x = 50; console.log(x);} // as function declaration

let doSomething = function() {let x = 50; console.log(x);}; // as function expression, which is an anonymous function assigned to the variable 'doSomething'

let doSomething = () => {let x = 50; console.log(x);}; // as arrow function

// let's transform it further

let doSomething = () => {console.log(50)}; //

// that is equivalent to ---- let doSomething = () => {console.log(50); return undefined};
// or even to           ---- let doSomething = () => {return ( console.log(50) ) };
// because anyways, *console.log* has *return undefined* in it, as explained above

//which is the same as  ---- let doSomething = () => {return console.log(50) };

// let's now apply the rules 2 and 3 from above, one by one:

let doSomething = () => return console.log(50);

let doSomething = () => console.log(50);

// Obviously, this just shows how we could rewrite many usual functions (functions declarations) into arrow functions
// we can do that safely if we don't have any **this** involved in the functions, of course
// also, from all lines of code above only one must remain, for example the last one.

// the last one, despite only having ---- console.log(50) --- as the execution aspect, it also ---- returns undefined ---- as well

// obviously ---- console.log( typeof doSomething );   // function
// while     ---- console.log( typeof doSomething() ); // undefined

If an arrow function has 2 or more parameters, we cannot omit the parentheses around them:

function sum(a, b) {let total = a + b; return total}

let sum = function(a, b) {let total = a + b; return total};
// or
let sum = (a, b) => {let total = a + b; return total};
// or
let sum = (a, b) => {return a + b};
// or
let sum = (a, b) => a + b;

For simple operations as above, the fat arrow sign '=>' can be "read" as is transformed into, in other words, a and b is (are) transformed into a + b.

Opposite to that, there are also functions that validate some data (for example checking the data type, etc), like this one

let isNumber = x => typeof x === "number";
// or
let isNumber = (x) => {return (typeof x === "number")};
// obviously, 
isNumber("Hello, John!"); // false

Those DON'T transform the data, and thus the arrow sign can be read something more as with the condition that, or similar.

In other words, a function like

let double = x => x * 2    // 'double' is a function that transforms x into x*2

is not the same as a checking one (mostly used in filters, sort, and other kind of validating functions, usually as callback function, etc)

let isArray = arr => Array.isArray(arr) // that last one already returns boolean by itself, no need to write return (Array.isArray() etc)

Last thing to know about return is that when you write code in multiple lines, the ASI (Automatic Semicolon Insertion) will insert a ';' after return if you mistakenly press enter after writing the return word, which will break the code, therefore instead of

return
a+b;

your code will behave as

return;
a+b;

so you better write the code with parentheses as here:

return (
  a + b
);

as explained in MDN website here, too.

Not the answer you're looking for? Browse other questions tagged or ask your own question.