0

I realize that an arrow function body can be contained by brackets, but when it doesn't have brackets, what determines when the function terminates?

I'm not sure if this question is general for ES6 or if it is specific to ReactJS or JSX, but I have the following function in React, and right below it, I have the start of a class declaration, which is not within the scope of the function:

const Search = ({ value, onChange, children }) =>
  <form>
    {children} <input 
      type="text"
      value={value} 
      onChange={onChange}
    />
  </form>

class Table extends Component {
  ...
  ...
  ...

This appears to be valid. What is it about the function that makes it not include the class declaration? Is it that there is a blank line between them? Is it something specific to JSX? Is it because there is a single container element as the body of the function? Or is it something else?

JCollier
  • 1,102
  • 2
  • 19
  • 31
  • [ASI](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Automatic_semicolon_insertion) - This is part of the ECMAScript standard and nothing to do with JSX or ES6 specifically. – Patrick Roberts Dec 20 '18 at 23:14
  • 2
    When the "function" has no brackets and contains only a single statement, the resulting value of that statement is returned. Yours contains only a single statement, which itself is a JSX value. – David Dec 20 '18 at 23:23
  • It's also worth pointing out that the JSX will be compiled into a call to `React.createElement(...)` - before the browser even sees it.After that, yes, ASI takes over and realises that this function call was supposed to be the end of the statement begun by `const Search = ...` – Robin Zigmond Dec 20 '18 at 23:36
  • 2
    The `
    ...
    ` is turned into `React.createElement(...)` so essentially the function is just returning that.
    – spencer.sm Dec 20 '18 at 23:43

2 Answers2

1

You can enclose your arrow functions with {}

const doSomething = () => {
  // ...
  return 'val'; // return statement is optional
}

If your arrow functions have only one line of code, it is implicitly understood that it is a return statement and you don't have to wrap them in {}

For example, both these functions are the same.

// explicit return
const doSomething = () => {
  return 'val';
}

// implicit return
const doSomething = () => ('val')

You can write implicit return in a few different ways

// implicit return with ()
const doSomething = () => ('val')

// implicit return without ()
const doSomething = () => 'val'

// implicit return in next line with ()
const doSomething = () => 
  ('val')

// implicit return in next line without ()
const doSomething = () => 
  'val'

This is what React does. Top level <tag> in a React component, when babel transpiled, will return on statement like React.createElement(...)

For example, this

const Search = ({ value, onChange, children }) =>
  <form>
    {children} <input 
      type="text"
      value={value} 
      onChange={onChange}
    />
  </form>

will be transpiled to

const Search = ({ value, onChange, children }) => React.createElement(...)
Dinesh Pandiyan
  • 5,814
  • 2
  • 30
  • 49
0

You return a single expression in the Search declaration. A compiler reads the declaration ending at the end of that expression (being the closing jsx tag). Personally i prefer to wrap my jsx () => (<div></div>) simply for readability but there's nothing wrong with how your code is.

Josh Kelly
  • 938
  • 5
  • 12
  • 1
    Since *statement* has a very specific meaning in JavaScript, this is not a statement here, it's an *expression*. – Felix Kling Dec 21 '18 at 02:04