This question already has an answer here:
Why doesn't my arrow function return a value?
(1 answer)
Closed 5 years ago.
Suppose we have a function using ES6 syntax like this:
const AccountOverview = (props) => {
const overviewVisible = props.overviewVisible;
const accountNumber = props.accountNumber;
const toggleAccountOverview = props.toggleAccountOverview;
const onClick = (e) => {
e.preventDefault();
toggleAccountOverview(!overviewVisible, accountNumber);
};
// FIXME: eslint WHY??????
/* eslint-disable */
return (
<div
className={props.overviewVisible ? 'acc-block open' : 'acc-block'}
>
<div>
)
}
and a function like this:
const AccountDetails = props => (
<div className="tabInner">
</div>
)
Why the first function is declared using {} and the second function is declared using just ()?
{} means the body of the arrow function, which can contain multiple statements. In this case you need to use return explicitly to return data from your function.
Without {}, your arrow function must have a single statement body which result will be returned implicitly without return statement.
The () is in that situations where you need to return an object within single statement body. Like
const getObject = () => ({ name: 'Test' });
Without () it will consider {} of the object the function body and give you an error.
Related
I'm currently taking an online course to learn React and I'm confused as to when I should be using { vs (.
I have 3 files:
App.js
const App = () => {
card-list.component.jsx
const CardList = ({ monsters }) => (
card.component.jsx
const Card = ({ monster }) => {
This is the code that currently works. Notice that on the second code the last character used is (. I thought of changing it to { to make it consistent with the other files but somehow the card list no longer shows up on the page although I didn't get any compile errors.
Can someone explain this to me and tell me when I should use one over the other?
This essentially is a feature of arrow functions in js.
const myArrowFunc = ({key1}) => ("Hello there! " + key1);
is essentially the same as
const myArrowFunc = ({key1}) => { return "Hello there! " + key1 };
when you leave out the curly brackets, the return is implicit.
When you include the curly brackets, you must explicitly use the return statement.
const someObj = { key1: "value1" };
const someReturn = myArrowFunc(someObj);
console.log(someReturn); // logs "Hello there! value1" to the console
()=>{} is the syntax of arrow function
When an arrow function only contains one line that return a value, e.g.:
() => {
return 1;
}
it can be simplified to
() => 1
Now what if you want to return an object directly? i.e. how to simplify
() => {
return { foo: "bar" }
}
Since an object also use {}, you cannot write {foo: "bar"} directly after the arrow as it will be treated as the function body. Wrapping the object within () solves the problem since a () chunk must be an expression. The above example can be simplified to
() => ( { foo : "bar" } )
This question already has answers here:
What does `return` keyword mean inside `forEach` function? [duplicate]
(2 answers)
JavaScript: Difference between .forEach() and .map()
(17 answers)
Closed 23 days ago.
I have a JS function in my code that is supposed to return a React Component for Each element of my split string, but for some reason, when I call it on my main "return()", the function isn't returning anything. I tried to put the function directly inside of the return(), but the same happened. That never happened to me before and I have no idea of what it is.
Here is my code:
import React from 'react';
import DatabaseLiLine from './DatabaseLiLine';
const DatabaseLiSection = ({ className, children, classId }) => {
const example = "Use,This,As,An,Example";
const splitLiTitles = example.split(",");
const returnLines = () => {
splitLiTitles.forEach(element => {
return(
<DatabaseLiLine>
{element}
</DatabaseLiLine>
);
})
}
return (
<li className={className}>
{children}
<div id={classId} className="consult_box">
{returnLines()}
</div>
</li>
);
}
export default DatabaseLiSection;
forEach doesn't return anything. Change your code to use map method.
const returnLines = () => {
splitLiTitles.map(element => {
return(
<DatabaseLiLine>
{element}
</DatabaseLiLine>
);
})
}
Having a little brain fart here but I forget if you also need to return the map method, like adding return before splitLiTitles.map.... I think it should work without it, but if it doesn't try adding that return in front as well.
I have been reading a bunch of React code and I see stuff like this that I don't understand:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
That is a curried function
First, examine this function with two parameters …
const add = (x, y) => x + y
add(2, 3) //=> 5
Here it is again in curried form …
const add = x => y => x + y
Here is the same1 code without arrow functions …
const add = function (x) {
return function (y) {
return x + y
}
}
Focus on return
It might help to visualize it another way. We know that arrow functions work like this – let's pay particular attention to the return value.
const f = someParam => returnValue
So our add function returns a function – we can use parentheses for added clarity. The bolded text is the return value of our function add
const add = x => (y => x + y)
In other words add of some number returns a function
add(2) // returns (y => 2 + y)
Calling curried functions
So in order to use our curried function, we have to call it a bit differently …
add(2)(3) // returns 5
This is because the first (outer) function call returns a second (inner) function. Only after we call the second function do we actually get the result. This is more evident if we separate the calls on two lines …
const add2 = add(2) // returns function(y) { return 2 + y }
add2(3) // returns 5
Applying our new understanding to your code
related: ”What’s the difference between binding, partial application, and currying?”
OK, now that we understand how that works, let's look at your code
handleChange = field => e => {
e.preventDefault()
/// Do something here
}
We'll start by representing it without using arrow functions …
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
};
};
However, because arrow functions lexically bind this, it would actually look more like this …
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
}.bind(this)
}.bind(this)
Maybe now we can see what this is doing more clearly. The handleChange function is creating a function for a specified field. This is a handy React technique because you're required to setup your own listeners on each input in order to update your applications state. By using the handleChange function, we can eliminate all the duplicated code that would result in setting up change listeners for each field. Cool!
1 Here I did not have to lexically bind this because the original add function does not use any context, so it is not important to preserve it in this case.
Even more arrows
More than two arrow functions can be sequenced, if necessary -
const three = a => b => c =>
a + b + c
const four = a => b => c => d =>
a + b + c + d
three (1) (2) (3) // 6
four (1) (2) (3) (4) // 10
Curried functions are capable of surprising things. Below we see $ defined as a curried function with two parameters, yet at the call site, it appears as though we can supply any number of arguments. Currying is the abstraction of arity -
const $ = x => k =>
$ (k (x))
const add = x => y =>
x + y
const mult = x => y =>
x * y
$ (1) // 1
(add (2)) // + 2 = 3
(mult (6)) // * 6 = 18
(console.log) // 18
$ (7) // 7
(add (1)) // + 1 = 8
(mult (8)) // * 8 = 64
(mult (2)) // * 2 = 128
(mult (2)) // * 2 = 256
(console.log) // 256
Partial application
Partial application is a related concept. It allows us to partially apply functions, similar to currying, except the function does not have to be defined in curried form -
const partial = (f, ...a) => (...b) =>
f (...a, ...b)
const add3 = (x, y, z) =>
x + y + z
partial (add3) (1, 2, 3) // 6
partial (add3, 1) (2, 3) // 6
partial (add3, 1, 2) (3) // 6
partial (add3, 1, 2, 3) () // 6
partial (add3, 1, 1, 1, 1) (1, 1, 1, 1, 1) // 3
Here's a working demo of partial you can play with in your own browser -
const partial = (f, ...a) => (...b) =>
f (...a, ...b)
const preventDefault = (f, event) =>
( event .preventDefault ()
, f (event)
)
const logKeypress = event =>
console .log (event.which)
document
.querySelector ('input[name=foo]')
.addEventListener ('keydown', partial (preventDefault, logKeypress))
<input name="foo" placeholder="type here to see ascii codes" size="50">
Briefly
It is a function that returns another function written in a short way.
const handleChange = field => e => {
e.preventDefault()
// Do something here
}
// is equal to
function handleChange(field) {
return function(e) {
e.preventDefault()
// Do something here
}
}
Motivation
This technique can be utilized in a scenario where we have a callback function with fixed parameters, but we need to pass additional variables while avoiding global variables.
For instance, we have a button that has an onClick callback, and we want to pass a variable, such as id, but onClick accepts a single argument, event, making it impossible to pass id along with event.
const handleClick = (event, id) {
event.preventDefault()
// Dispatch some delete action by passing record `id`
}
It is not going to work.
Here as a solution, we write a function that returns another function with id in its variables scope without using any global variables:
const handleClick = id => event {
event.preventDefault()
// Dispatch some delete action by passing record `id`
}
const Confirm = props => (
<div>
<h1>Are you sure to delete?</h1>
<button onClick={handleClick(props.id)}>
Delete
</button>
</div
)
Function composition
Multiple arrow functions also are called "curried functions" and are used for function compositions.
import {compose} from 'redux'
import {store} from './store.js'
const pickSelectedUser = props => {
const {selectedName, users} = props
const foundUser = users.find(user => user.name === selectedName)
return foundUser.id
}
const deleteUser = userId => event => {
event.preventDefault()
store.dispatch({
type: `DELETE_USER`,
userId,
})
}
// The compose function creates a new function that accepts a parameter.
// The parameter will be passed throw the functions from down to top.
// Each function will change the value and pass it to the next function
// By changing value it was not meant a mutation
const handleClick = compose(
deleteUser,
pickSelectedUser,
)
const Confirm = props => (
<div>
<h1>Are you sure to delete?</h1>
<button onClick={handleClick(props)}>
Delete
</button>
</div
)
A general tip: If you get confused by any of new JavaScript syntax and how it will compile, you can check Babel. For example, copying your code in Babel and selecting the ES 2015 preset will give an output like this
handleChange = function handleChange(field) {
return function (e) {
e.preventDefault();
// Do something here
};
};
Understanding the available syntaxes of arrow functions will give you an understanding of what behaviour they are introducing when 'chained' like in the examples you provided.
When an arrow function is written without block braces, with or without multiple parameters, the expression that constitutes the function's body is implicitly returned. In your example, that expression is another arrow function.
No arrow funcs Implicitly return `e=>{…}` Explicitly return `e=>{…}`
---------------------------------------------------------------------------------
function (field) { | field => e => { | field => {
return function (e) { | | return e => {
e.preventDefault() | e.preventDefault() | e.preventDefault()
} | | }
} | } | }
Another advantage of writing anonymous functions using the arrow syntax is that they are bound lexically to the scope in which they are defined. From 'Arrow functions' on MDN:
An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value. Arrow functions are always anonymous.
This is particularly pertinent in your example considering that it is taken from a reactjs application. As as pointed out by #naomik, in React you often access a component's member functions using this. For example:
Unbound Explicitly bound Implicitly bound
------------------------------------------------------------------------------
function (field) { | function (field) { | field => e => {
return function (e) { | return function (e) { |
this.setState(...) | this.setState(...) | this.setState(...)
} | }.bind(this) |
} | }.bind(this) | }
Think of it like this, every time you see a arrow, you replace it with function.function parameters are defined before the arrow.
So in your example:
field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}
and then together:
function (field) {
return function (e) {
e.preventDefault();
};
}
From the docs:
// Basic syntax:
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
// equivalent to: => { return expression; }
// Parentheses are optional when there's only one argument:
singleParam => { statements }
singleParam => expression
It might be not totally related, but since the question mentioned react uses case (and I keep bumping into this SO thread): There is one important aspect of the double arrow function which is not explicitly mentioned here.
Only the 'first' arrow(function) gets named (and thus 'distinguishable' by the run-time), any following arrows are anonymous and from React point of view count as a 'new' object on every render.
Thus double arrow function will cause any PureComponent to rerender all the time.
Example
You have a parent component with a change handler as:
handleChange = task => event => { ... operations which uses both task and event... };
and with a render like:
{
tasks.map(task => <MyTask handleChange={this.handleChange(task)}/>
}
handleChange then used on an input or click. And this all works and looks very nice. BUT it means that any change that will cause the parent to rerender (like a completely unrelated state change) will also re-render ALL of your MyTask as well even though they are PureComponents.
This can be alleviated many ways such as passing the 'outmost' arrow and the object you would feed it with or writing a custom shouldUpdate function or going back to basics such as writing named functions (and binding the this manually...)
The example in your question is that of a curried function which makes use of arrow function and has an implicit return for the first argument.
Arrow function lexically bind this i.e they do not have their own this argument but take the this value from the enclosing scope
An equivalent of the above code would be
const handleChange = (field) {
return function(e) {
e.preventDefault();
/// Do something here
}.bind(this);
}.bind(this);
One more thing to note about your example is that define handleChange as a const or a function. Probably you are using it as part of a class method and it uses a class fields syntax
so instead of binding the outer function directly, you would bind it in the class constructor
class Something{
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(field) {
return function(e) {
e.preventDefault();
// do something
}
}
}
Another thing to note in the example is the difference between implicit and explicit return.
const abc = (field) => field * 2;
Above is an example of implicit return ie. it takes the value field as argument and returns the result field*2 which explicitly specifying the function to return
For an explicit return you would explicitly tell the method to return the value
const abc = () => { return field*2; }
Another thing to note about arrow functions is that they do not have their own arguments but inherit that from the parents scope as well.
For example if you just define an arrow function like
const handleChange = () => {
console.log(arguments) // would give an error on running since arguments in undefined
}
As an alternative arrow functions provide the rest parameters that you can use
const handleChange = (...args) => {
console.log(args);
}
This question already has answers here:
What are the rules for JavaScript's automatic semicolon insertion (ASI)?
(7 answers)
Closed 4 years ago.
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?
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(...)
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.
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>
);
}
}
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})
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})
If you only write () => {} this explicitly means that the function does more than 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 translates to:
function createUser(x) {
prop:x
}
With parenthesis, you are still using the default return from the arrow function.
const createUser = (name, email) => ({})
function createUser(name, email) { return {} )