JavaScript do expression: if statement without else - javascript

I have a question about the proposed JavaScript do expression construct. There are many examples that show how it can be used to return a value from a conditional statement that has both if and else. Also valid for if with else if and else.
What about a conditional that has just an if clause but no else if or else? Is this valid usage of the do expression?
My use case is for conditionally displaying content in a React component. I would like to write JSX code like so, but I am not sure if it is valid:
export default function myComponent(props) {
return (
<div>
{do {
if (true) {
<p>If statement is true</p>
}
}}
<p>I am always rendered</p>
</div>
);
}
I also asked the question in this gist.

Not sure about do, also as mentioned by #Felix Kling
do expression is a stage 1 proposal, not part of ES2016 (ES7).
You can write it like this using ternary operator, and return null if condition fails:
export default function myComponent(props) {
return (
<div>
{
true?
<p>If statement is true</p>
:null
}
<p>I am always rendered</p>
</div>
);
}
Or Use && Operator:
export default function myComponent(props) {
return (
<div>
{
true && <p>If statement is true</p>
}
<p>I am always rendered</p>
</div>
);
}
Check the DOC for more details about Conditional Rendering.

Why not simply do this ? Using the Ternary operator
export default function myComponent(props) {
return (
<div>
{ true ? <p>If statement is true</p> : null }
<p>I am always rendered</p>
</div>
);
}

Here is what Babel does:
Input:
<p>
{do {
if (true) {
<a/>
}
}}
</p>
Output:
React.createElement(
"p",
null,
true ? React.createElement("a", null) : void 0
);
This makes sense to me. The return value in the implied else would be undefined.

You can do it simply, using conditioanl rendering:
{condition && jsx-element}
Example:
{relationshipStatus===RelationshipStatus.SINGLE && <ShowIAmSingleComponent />}
Whenever this relationshipStatus takes value of RelationshipStatus.SINGLE, it will render this ShowIAmSingleComponent component.
Simple as react.

Yes, it is a valid syntax to write a do expression without an else and it will return an undefined (void 0).
let a = do {
if (false) true
}
// a === undefined
We can also return a value at the end without even using else like this:
let a = do {
if (false) true
null
}
// a === null
Especially for ReactJS, we have to return a null even using the do expression, because if it doesn't return something, the return value will be undefined which of course will error break the component rendering:
export default function myComponent(props) {
return (
<div>
{do {
if ([condition]) {
<p>If statement is true</p>
}
null
}}
<p>I am always rendered</p>
</div>
);
}
Or, use the Nullish coalescing operator ?? which will also catch undefined:
export default function myComponent(props) {
return (
<div>
{do {
if ([condition]) {
<p>If statement is true</p>
}
} ?? null}
<p>I am always rendered</p>
</div>
);
}
Other answers here suggest why bother using do expression since we can do this using the Conditional (ternary) operator ?:, and the answer is that using the ternary operator when we'll have more than one condition won't be syntactical friendly and it will lead in miss-renders and hard time understanding the logic for developers:
export default function myComponent(props) {
return (
<div>
{[condition1]
? <p>If condition1 is true</p> :
[condition2]
? <p>If condition2 is true</p> :
[condition2]
? <p>If condition3 is true</p> :
[condition4]
? <p>If condition4 is true</p> :
null
}
<p>I am always rendered</p>
</div>
);
}
and that's one of the reasons behind the proposal and existence of the do expression; it will make multiple conditional expressions syntactical friendly:
export default function myComponent(props) {
return (
<div>
{do {
if ([condition1]) <p>If condition1 is true</p>
if ([condition2]) <p>If condition2 is true</p>
if ([condition3]) <p>If condition3 is true</p>
if ([condition4]) <p>If condition4 is true</p>
} ?? null}
<p>I am always rendered</p>
</div>
);
}

Related

Displaying components depending on one variable with multiple variables as conditions

I want to display a component depending on a variable. The variable should be able to hold a flexible amount of conditions/types.
Example:
I want to display my component if test1 === false or test2 equals a number greater than 0. But also should allow to expand. Here is what I am trying so far.
const test1 = false
const test2 = 10
const conditionVar = test1 === false || test2 > 0
return (
{
conditionVar ? <MyComponent /> : null
}
)
Questions would be if this is good or bad practise? Can I extend this for example if I needed test3, test4... variables in the future as conditions? Will it be safe and run as expected every time?
That's common practice when it's inside a larger JSX structure, although with your specific example there's no reason to be indirect, just:
return conditionVar ? <MyComponent /> : null;
If you know conditionVar will be null, undefined, or false (specifically) when you don't want to render or any truthy when you do, you can also do:
return conditionVar && <MyComponent />;
Or in a larger structure:
return <div>
{/*...something...*/}
{conditionVar && <MyComponent />}
</div>;
But another option is to just set a variable to the thing you want to render:
const component = !test1 || test2 > 0
? <MyComponent />
: null;
then when rendering, use component:
return component;
or in a larger structure:
return <div>
{/*...something...*/}
{component}
</div>;
They're all fine in context.
Like others have mentioned, you approach is fine. However, I would argue that in a more complex situation, it would be more readable to put the different conditions and renders one after another.
Also, you can utilise early returns so that if there is no data to display, your component will exit immediately.
Here's an example:
if (noData) {
return null;
}
if (condition1) {
return <Component1 />;
}
if (condition2) {
return (
<div>
<Component2A />
<Component2B />
...
</div>
);
}
Having this in mind, I would rewrite your example like this:
if (test1 && test2 <= 0) {
return null;
}
return <MyComponent />;
Note: test1 is not precisely the same as the negative of test1 === false but i believe that's what the intention was.

Conditional Rendering in ReactJs for one part in Html

I want to render some part of Html only if one of the variable is true. I have seen examples where I can return the whole element but I only want a if condition on one part of the html. I only want to show with 10 lines if one of the variables is true but html with 500 lines is common. Can I do that in return function?
const getCustomers= (props) => {
useEffect(() =>{ do something...});
return (
<>
if(test === true){
<div> 10 lines</div>
else
{
do not show this div
}
}
<div> 500 lines</div> // Common
</>
)
};
Conditional rendering is only supported using ternary operator and logical and operator:
{
something ? '10 lines' : '500 lines'
}
{
something && '10 lines' || '500 lines'
}
if-else statements don't work inside JSX. This is because JSX is just syntactic sugar for function calls and object construction.
For further details, you may read this, and the docs
Try to avoid logic inside of your return statements.
You can assign your conditional output to a JSX value, and always render it.
const Customers = () => {
const optionalDiv = test === true && <div>10 lines</div>;
return (
<>
{optionalDiv}
<div>500 lines</div>
</>
);
};
you can use conditional (ternary) operator
return (
<>
{ test === true ? (<div> 10 lines</div>) : null }
<div> 500 lines</div>
</>
)
I think just doing it like this should do it -
return (
<>
{test? <div> 10 lines</div> : null}
<div> 500 lines which are common</div>
</>
);

minor error in if statement in render function

I have an error notification point at my if statement that checks if the length > 0. Not sure what the reason is for this? Think it must be a very stupid curly bracket or something but just can't see it...
render() {
return (
<DefaultLayout>
<div className="innercircleboxes">
{
if(this.state.friends.filter(friend => (this.state.innerCircle).includes(friend._id)).length > 0){
this.state.friends.filter(friend => (this.state.innerCircle).includes(friend._id)).map(inner =>
<div key={inner._id}>
<InnerCircleDetail
key={inner._id}
id={inner._id}
username={inner.username}
location={inner.location}
/>
</div>
)
}
}
</div>
</div>
You can't use if statements inside JSX. You must use expressions. Say the ternary operator
{a > b ? x : y}
Or in your case this would make more sense
{isTrue && <RenderMe/>}
Relevant link.

Can i use multiple state value inside conditional rendering - ReactJs

I wonder how can use two state based booleans inside of the conditional rendering . For example i want to render a certain <div> element if one of the conditions are truthy and otherwise don't render it
Example :
{
this.state.visible && this.state.checked &&
<div>
...
</div>
}
In order to display my error message i use this example , but init i have the .length of the object so it is easy to use like :
{
this.state.ErrorMessage.length > 0 &&
<p>Error 404</p>
}
Can somebody give me heads up ? I am a little bit confused .
You can follow your way by parenthesis, to check both are true:
{
(this.state.visible && this.state.checked) && <div>...</div>
}
if you want one of is true:
{
(this.state.visible || this.state.checked) && <div>...</div>
}
Use it as a separate function which returns the components based on condition.
Example :
renderConditionalComponent() {
const { visible, checked } = this.state;
if (visible || checked) {
return <Component1 />;
}
// There could be other condition checks with different components.
// ...
return null;
}
render() {
// ...
return (
<div>
{this.renderConditionalComponent()}
{/* other components, etc */}
<OtherComponent />
</div>
);
}

jsx if else shorthand to hide element

I can do
<p>Company: {{this.state.user.company}}</p>
but sometime company has no value. So how should I hide the entire if the property of company is null?
I tried
<p>({this.state.user.company} ? 'Company: ' + {this.state.user.company} : '')</p>
But it doesn't work.
React doesn't render falsy values, so you can use short-circuit evaluation. If this.state.user.company is null, it will be ignored by react. If it's truthy, react will render the element after &&.
render() {
return (
<div>
{this.state.user.company &&
<p>Company: {this.state.user.company}</p>
}
</div>
);
}
Alternative syntax to Ori Drori's answer (I find this a bit easier to read):
render() {
return (
{this.state.user.company ? <p>Company: {this.state.user.company}</p> : null}
)
}
Another alternative:
render() {
if (!this.state.user.company) return (<p>Loading...</p>)
return (
<div>
<p>Name: {this.state.user.company.name}</p>
<p>Address: {this.state.user.company.address}</p>
<p>Creation date: {this.state.user.company.creation}</p>
</div>
)
}
You could also use the following for a short handed format:
render() {
return (
{this.state.user.company ?? <p>Company: {this.state.user.company}</p>}
)
}
Reference Nullish coalescing operator (??)

Categories