As per the React Docs we can have two ways for setState one with object syntax and other with function which they have shown as below
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
My understanding of arrow function syntax is like () => {}
where flower brackets are followed after arrow =>
, but as per the sample it is round braces instead of flower brackets
What is the difference between these syntax ()=>{}
and ()=>({})
.
Sample Code tried as per the docs which is working when this.setStage(prevStage=>({}))
syntax is used in handleClick
function, and if you change it to this.setState(prevStage=>{})
it wont toggle the button value.
Below is the working code:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {
isToggleOn : true
}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<div>
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : "OFF"}
</button>
</div>
);
}
}
The setState() Method State can be updated in response to event handlers, server responses, or prop changes. This is done using the setState() method. The setState() method enqueues all of the updates made to the component state and instructs React to re-render the component and its children with the updated state.
The () => { ... } is the function. It's an ES6-style "arrow" function expression. These are like function expressions ( tick = function() { ... } ) except that the this value within the function is inherited from the context in which it's defined rather than being set when the function is called.
Note how setState() works. You pass it an object containing part(s) of the state you want to update. In other words, the object you pass would have keys corresponding to the keys in the component state, then setState() updates or sets the state by merging the object to the state. Thus, “set-State”.
There are 2 main issues to consider here:
How arrow functions works?
What setState
expects when passing function
as a parameter?
Answers:
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
.
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.
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})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With