Arrow function without curly braces

JavascriptReactjsEcmascript 6Arrow Functions

Javascript Problem Overview


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');
};

Javascript Solutions


Solution 1 - Javascript

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

Solution 2 - Javascript

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

Solution 3 - Javascript

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 };

Solution 4 - Javascript

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' }
}

Solution 5 - Javascript

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

Solution 6 - Javascript

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

Solution 7 - Javascript

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

Solution 8 - Javascript

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.

Solution 9 - Javascript

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondkimotView Question on Stackoverflow
Solution 1 - JavascriptdavidView Answer on Stackoverflow
Solution 2 - JavascriptGrayedFoxView Answer on Stackoverflow
Solution 3 - JavascriptAmerllicAView Answer on Stackoverflow
Solution 4 - JavascriptAbhishek KumarView Answer on Stackoverflow
Solution 5 - JavascriptFasemore MandelaView Answer on Stackoverflow
Solution 6 - JavascriptJaiedView Answer on Stackoverflow
Solution 7 - JavascriptMarcio S GalliView Answer on Stackoverflow
Solution 8 - JavascriptRandel RamirezView Answer on Stackoverflow
Solution 9 - JavascriptEveView Answer on Stackoverflow