score:15

Accepted answer

There are 2 main issues to consider here:

  1. How arrow functions works?

  2. What setState expects when passing function as a parameter?

Answers:

  1. Arrow functions can return a value implicitly or explicitly.
    When there is no function body (no curly brace {}) then you are returning implicitly:

    const x = () => 'we are returning a string here';  
    

    When we use a function body, we need to use the return key word:

    const x = () => {
      return 'another string returned'
    };
    

    There is another option to return something without the return key word, you can wrap the curly brace with parentheses () and this will signal the engine that the curly brace are not a function body but an object, this is considered as creating an expression:

    const x = () => ({myKey: 'some string'});
    

    This is similar as we usually do with function expressions.
    Especially with IIFE (Immediately Invoked Function Expression) :

    (function() {
        //some logic...
    })();  
    

    If we will not return anything, then the function will just return undefined.

  2. As for setState, when you pass a function as a parameter, it expect that this function will return an object.
    When your function didn't return anything (as stated above) it actually returned undefined.
    JavaScript won't yield an error as this is not an error. its just a function that returns nothing (undefined).

Here is a running example of your code without the wrapping parentheses:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isToggleOn: true
    }
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => {
      return { // we must return an object for setState
        isToggleOn: !prevState.isToggleOn
      } 
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>
          {this.state.isToggleOn ? 'ON' : "OFF"}
        </button>
      </div>
    );
  }
}


ReactDOM.render(<Toggle />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Edit
As a followup to your comments

I would expect Javascript to throw error when we return just key : value without enclosing parenthesis, i.e., () => {key:value} - which means it is trying to return 'key:value' and not Object, and this should be an JS error, but it did not throw any error. Please correct me if my understanding is wrong

It is not returning a key value, it is a "void" function that returns undefined.
See this running snippet:

const x = () => {myKey: 'myValue'};
const y = x();
console.log(y);

Edit#2
Followup to your other comments (which is basically kind of a whole different question in my opinion).

let y = function() {'abc':1} - syntax error, let y = function(){abc:1} and let y = function(){ return {'abc':1} } - no error, where first one (syntax error) we are trying to assign 1 to string abc, which is same as 3rd sample (no error), and 2nd example assigning 1 to abc - works when there is no quotes. Please explain the difference of these 3 samples and why 1st one fails and not 2nd example

OK, this is getting interesting.

where first one (syntax error) we are trying to assign 1 to string abc...

No we are not.
We are trying to create a label:, but labels can't be strings!
Same as variables can't be strings - var 'x' = 1.

This is a valid syntax in JavaScript:

const y = function(){b:2};

What we are doing here is creating a label: named a and this label has an expression of 1 (we are not doing anything with this label.).

const x = () => {a:1};
const y = function(){a:1};

This syntax is invalid:

const y = function() { 'a': 1 };

This is not valid because labels can't start with a string:

const x = () => { 'a': 1 };
const y = function() { 'a': 1 };

And again, this is not a key:value pair, the curly brace are the function's BODY.

score:0

If you only write () => {} this explicitally means that the function does more than just return something.

For example:

const logAndReturn = (val) => {
  console.log(val)
  return val
}

But let's say you have a function that takes params and returns an object based on those params.

const createUser = (x) => { 
  prop: x
}

This will prompt an error, cause this basically translates to:

function createUser(x) { 
  prop:x 
}

With paranthesis you are still using the default return from the arrow function.

const createUser = (name, email) => ({})
function createUser(name, email) { return {} )

score:1

the simple answer is

()=>({})

also it's equal to

()=> {
   return {}
 }

return an empty object,here parentheses around {} mean return. also you know we must pass object to setState so we insert any thing we want to state between {}

()=>({any thing you want to set to state})

score:11

Later I referred MDN and found details under Advanced Syntax section, that if you want to return objects implicitly then we need to enclose it within () , that answered my question.

// Parenthesize the body of function to return an object literal expression:

params => ({foo: bar})


Related Query

More Query from same tag