I'm having a hard time understanding the following ES6 syntax. I read the docs quite a bit and it seems like there is more than one change happening here:
const renderInput = props =>
<div>
<label>{props.placeholder}</label>
</div>
Would the above be equivalent to:
const renderInput = function renderInput(props) {
return <div>
<label>{props.placeholder}</label>
</div>
}
?
Yes, that is correct. When you have only one expression, and it's the expression you wish to return from the function, you may omit the curly brackets.
Since <div><label>{props.placeholder}</label></div> is, in fact, a single expression (it gets transpiled to React.createElement(......) or something like that), and you wish to return it from renderInput, that is indeed how you use the no-brackets version of the arrow function.
If you had wished to use variables or do some other computation (conditions, for loops, etc), you wouldn't have been able to omit the brackets.
Related
Before proceeding, I should mention that yes, I have already read the questions and answers on "Use if statement in React JSX" and its different variants on SO and elsewhere.
However, these posts are more about how to get around without using statements in JSX. I'd like to know why statements aren't allowed in JSX, for which I cannot find any posts on.
I am reading the official documentation on this called "If-Else in JSX", and the reason given for why is, quote,
JSX is just syntactic sugar for function calls and object construction
They go on to contrast the following two pieces of code, the first of which works and the second one doesn't work:
This is valid:
// This JSX:
ReactDOM.render(<div id="msg">Hello World!</div>, mountNode);
// Is transformed to this JS:
ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode);
This is not valid:
// This JSX:
<div id={if (condition) { 'msg' }}>Hello World!</div>
// Is transformed to this JS:
React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
I would really like to understand this under the hood. First of all, in the second example, I would never have thought to write JavaScript inside the id property of an HTML element. In fact, this is the first time I've seen code of any sort used in an id property. If I were to try to write an if conditional, I would just do it in curly braces within the render return expression, as a naïve analog of other JS that works (like map or ternary expression).
render() {
return (
{if ...
}
)
I have no doubt that it is perfectly clear to the author of this document that this slightly unorthodox example explains their assertion that "JSX is just syntactic sugar for function calls and object construction", but I cannot figure out how.
Let's start conceptually. What are the definitions of statement vs expression?
A statement does something. An expression evaluates to a value.
JSX is meant to be built up and passed around from one segment of your code to another, eventually ending up as HTML. The name even suggests this "JavaScript to XML" conversion.
The whole point of it is to return a "value" of HTML nodes. JSX kindly allows for expressions, because those help you determine values.
Perhaps it will help to take a closer look at the difference between a ternary expression and an if/else.
If/Else
if(isSaturday){
wakeUpHour = 10;
}else{
wakeUpHour = 7;
}
Ternary
wakeUpHour = isSaturday ? 10 : 7;
Those both accomplish the same thing, right? But under the hood they are operating differently. In English, the if/else might read:
If the value of 'isSaturday' is truthy, run the code inside the curly braces
Assign the number 10 to 'wakeUpHour'
Otherwise, run the code inside the next curly brace
Assign the number 7 to to 'wakeUpHour'
The ternary statement also has two parts:
If isSaturday is truthy, have a value of 10. Otherwise have a value 7.
Assign this value to 'wakeUpHour'
We think of those as accomplishing the same thing. The key point here is that the ternary expression itself is just a value. It's not lines of codes. To do something with that value required another part, assigning it.
In JSX, we don't want to be assigning things. We want values. So we are just taking the ternary expression (a value), not the assignment part or any other code statements.
Finally, and hopefully not to add to your confusion, I would note that you can define functions in JSX.
const myJSX = <button onClick={ () => { return 'hello'; } }>Say hello</button>
Wait, what? I thought we couldn't execute lines of code. It's not executing the lines of code, it's defining them; it's rendered to:
var myJSX = React.createElement("button", {onClick: () => {
return 'hello';
}}, "Say hello");
Compare that with trying to just throw in an if/else statement:
const myJSX = <span>{ if(true){ return 'hello'; } }</span>
Which would try to render as:
var myJSX = React.createElement("span", null, if(true){ return 'hello' });
That doesn't work, for the same reason that you can't normally pass an unencapsulated chunk of code into an argument of a function.
Maybe this is irrelevant to your question, but I've been redirected here because one of my questions said to be duplicate to your question.
if you want to do multi-line JavaScript code, you can wrap your JS code with an IIFE, for example:
<b>
{(() => {
const a = [1, 2, 3].find((el) => el === 2)
// as much code as you want ...
// ...
// ...
console.log(a)
})()}
</b>
I'm using the following package in my React application to generate a Recaptcha component: https://github.com/appleboy/react-recaptcha
Here is what the component looks like, with the eslint warning:
this.recaptchaRef is defined like so: this.recaptchaRef = React.createRef();
This ref allows me to reset the Recaptcha when there is an error with my form like so: this.recaptchaRef.reset();
How would I be able to resolve this error without writing ESlint comments?
Arrow functions, if there is no { following the =>, will return whatever expression follows. At the moment, your arrow function is assigning event to this.recaptchaRef and returning event. (even if the consumer completely ignores the return value, it'll still generate a linting error.) So, just use curly brackets to ensure nothing is returned:
ref={(event) => {
this.recaptchaRef = event;
}}
As per documentation of Arrow functions they can have either a "concise body" or the usual "block body".
In a concise body, only an expression is specified, which becomes the explicit return value. In a block body, you must use an explicit return statement.
So in the example that you are using, "concise body" is specified. Concise body means there is no surrounding curl braces. Hence even if there if no return keyword the expression is returned. Since you want to avoid returning the expression so you need to change the body to "block body" i.e. specify curl braces after => operator i.e.
ref = {event => {
this.recaptchaRef = event;
}};
I set an arrow function with a ternary operator in curly braces as the callback for setState but get an error message when I run the code.
If I remove the curly braces, the error goes away.
If I don't use a ternary operator the error goes away.
If I write "return" before the operator the error goes away.
The code works both ways (it looks like it runs some rescue method), but I don't understand why I am getting the error message to begin with. The function I am running doesn't need to return anything, just needs to run some statements. But it seems like React doesn't like ternary operators in callbacks? or they are ok if they are returned? does anyone know why?
this.setState({someObject},() => { x ? console.log("yo") : null;});
warning message
Expected an assignment or function call and instead saw an expression no-unused-expressions
something wrong with ternary operators in callback functions?
Its an ESLint warning, It is happening because you are not using the value that you have returned anywhere else and has no effect on the state of the program.
Unused expressions are those expressions that evaluate to a value but
are never used
you can read more about the rule here:
ESLint
The problem is that you aren't returning the result of the ternary expression (or doing anything with it), and the ternary operator is meant to be used when you need the resulting value. For similar reasons, the following lines would produce the same warning:
function foo() {
'bar';
}
and
function foo2() {
baz === 3;
}
The value of the evaluated expression is being discarded, just as it is in your situation. When you don't need to use the result of the expression, don't use the ternary operator; use if and else instead:
this.setState({someObject},() => {
if (x) console.log("yo");
});
The answer has to do with how arrow functions work:
When you write an arrow functions without curly braces then whats on the right of the arrow is considered an expression and JS knows to return the result of the expression.
But when curly braces are used then what is on the right of the arrow is a statement block which doesn't return anything unless instructed to therefore a return statement must be given implicitly in order for the function to return anything.
Sometimes, mostly in classes, I need to do a single line function.
For instance:
class Blah {
getVisibilityAnimValue() { return this.state.isVisible ? 100 : 0 }
}
In ES6 is there is any friendly way? I tried to omit the surrounding curlies and omitting the return but it's not working.
In ES6 is there is any friendly way?
No, there is not. As I think you already know, in order to use this to refer to the calling instance, you cannot use an arrow function (which uses the lexical this rather than a this based on how it was called). So, you have to use a conventional ES6 method definition. As such, you need the braces {} and you need the return.
The ES6 class syntax at least saves you the ES5 scheme of:
Blah.prototype.getVisibilityAnimValue = function() {...}
I tried to omit the surrounding curlies and omitting the return but it's not working.
Yep, those are still required.
If you had a lot of methods that worked just like this and used the identical logic, you could factor the logic into a shared function.
// define this once and then use it many places
function zVal(val) {
return val ? 0 : 100;
}
getVisibilityAnimValue() { return zVal(this.state.isVisible) }
But, for something this simple, it's arguable whether this is "better" since it now involves an extra function call and makes it a little harder to see (in a glance) what it does.
No. That is one of the exact reasons why arrow functions were created.
I saw the following line in a node js code base.
_ => { return resolve(abc);}
Can any one give me some hint on what this _ means?
I know => is fat arrow function. This line is from a snippet of promise.
At the coaxing of a discussion elsewhere in this question, I'll turn my comments into an answer.
First off, I assume you aren't asking about arrow functions in general, but are just curious about the _ in your code sample.
There is a convention (used by some) to declare and name a parameter to a callback function that you know is passed, but you are not going to be using with an underscore as a sort of placeholder. It's a signal to people reading the code that there is an argument being passed to this callback, but you don't plan on using it in this particular invocation. It's presence is not functional, but more for
Now, without knowing what was in the head of the developer who wrote the line of code you asked about, we can't know for sure what the underscore means, but it does appear to match that previously described convention. There is one argument to the callback and it is not used in the implementation of the callback.
So, if our guess that this is a use of that convention is true, then in the arrow function that you show:
_ => { return resolve(abc);}
It is likely expecting one argument, but this particular use of that callback does not plan on using it, thus they named it with an _ just to signal that.
Now, there is no particular reason in Javascript that the callback needs to even define a single argument like this that be used. The callback could just as well have been defined as:
() => { return resolve(abc);}
since there's no requirement in Javascript that you declare arguments you aren't going to use.
If the callback took two arguments and it was the first one that you weren't going to use, then it does have to be declared as something in order to allow access to the second argument:
(_, secondArg) => { return resolve(secondArg);}
It means that the arrow function argument is not used. They use _ as argument name for the arrow function.
Doesn't this mean something like this?
function(_){
return resolve(abc);
}
What's happening here is that the code is using (some of) the concise syntax for arrow functions. To do this you'd write a function like this:
var f = x => x*x;
according to the docs
So with your example, the argument x is named with an _ (a valid character for variable names):
var f = _ => {return resolve(abc)}
But, it doesn't need the return or the brackets, either. It could be just:
_ => resolve(abc);
Perhaps a more readable way to write it would be with the parathesis:
() => resolve(abc);