Reactjs setState arrow function syntax
There are 2 main issues to consider here:
How arrow functions works?
What
setState
expects when passingfunction
as a parameter?
Answers:
Arrow functions can return a value implicitly or explicitly.
Whenthere is no function body (no curly brace{}
) then you arereturning 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
keyword, you can wrap the curly brace with parentheses()
and thiswill signal the engine that the curly brace are not a function bodybut 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 FunctionExpression) :(function() { //some logic...})();
If we will not return anything, then the function will just return
undefined
.As for
setState
, when you pass a function as a parameter, itexpect that this function will return an object.
When your function didn't return anything (as stated above) it actuallyreturnedundefined
.
JavaScript won't yield an error as this is notan 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:
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.).
This syntax is invalid:
const y = function() { 'a': 1 };
This is not valid because labels can't start with a string:
And again, this is not a key:value
pair, the curly brace are the function's BODY.
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})
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})