TranslateProject/sources/tech/20180201 Conditional Rendering in React using Ternaries and.md
2018-02-02 15:20:07 +08:00

206 lines
7.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Conditional Rendering in React using Ternaries and Logical AND
============================================================
![](https://cdn-images-1.medium.com/max/2000/1*eASRJrCIVgsy5VbNMAzD9w.jpeg)
Photo by [Brendan Church][1] on [Unsplash][2]
There are several ways that your React component can decide what to render. You can use the traditional `if` statement or the `switch` statement. In this article, well explore a few alternatives. But be warned that some come with their own gotchas, if youre not careful.
### Ternary vs if/else
Lets say we have a component that is passed a `name` prop. If the string is non-empty, we display a greeting. Otherwise we tell the user they need to sign in.
Heres a Stateless Function Component (SFC) that does just that.
```
const MyComponent = ({ name }) => {
if (name) {
return (
<div className="hello">
Hello {name}
</div>
);
}
return (
<div className="hello">
Please sign in
</div>
);
};
```
Pretty straightforward. But we can do better. Heres the same component written using a conditional ternary operator.
```
const MyComponent = ({ name }) => (
<div className="hello">
{name ? `Hello ${name}` : 'Please sign in'}
</div>
);
```
Notice how concise this code is compared to the example above.
A few things to note. Because we are using the single statement form of the arrow function, the `return` statement is implied. Also, using a ternary allowed us to DRY up the duplicate `<div className="hello">` markup. 🎉
### Ternary vs Logical AND
As you can see, ternaries are wonderful for `if/else` conditions. But what about simple `if` conditions?
Lets look at another example. If `isPro` (a boolean) is `true`, we are to display a trophy emoji. We are also to render the number of stars (if not zero). We could go about it like this.
```
const MyComponent = ({ name, isPro, stars}) => (
<div className="hello">
<div>
Hello {name}
{isPro ? '🏆' : null}
</div>
{stars ? (
<div>
Stars:{'⭐️'.repeat(stars)}
</div>
) : null}
</div>
);
```
But notice the “else” conditions return `null`. This is becasue a ternary expects an else condition.
For simple `if` conditions, we could use something a little more fitting: the logical AND operator. Heres the same code written using a logical AND.
```
const MyComponent = ({ name, isPro, stars}) => (
<div className="hello">
<div>
Hello {name}
{isPro && '🏆'}
</div>
{stars && (
<div>
Stars:{'⭐️'.repeat(stars)}
</div>
)}
</div>
);
```
Not too different, but notice how we eliminated the `: null` (i.e. else condition) at the end of each ternary. Everything should render just like it did before.
Hey! What gives with John? There is a `0` when nothing should be rendered. Thats the gotcha that I was referring to above. Heres why.
[According to MDN][3], a Logical AND (i.e. `&&`):
> `expr1 && expr2`
> Returns `expr1` if it can be converted to `false`; otherwise, returns `expr2`. Thus, when used with Boolean values, `&&` returns `true` if both operands are true; otherwise, returns `false`.
OK, before you start pulling your hair out, let me break it down for you.
In our case, `expr1` is the variable `stars`, which has a value of `0`. Because zero is falsey, `0` is returned and rendered. See, that wasnt too bad.
I would write this simply.
> If `expr1` is falsey, returns `expr1`, else returns `expr2`.
So, when using a logical AND with non-boolean values, we must make the falsey value return something that React wont render. Say, like a value of `false`.
There are a few ways that we can accomplish this. Lets try this instead.
```
{!!stars && (
<div>
{'⭐️'.repeat(stars)}
</div>
)}
```
Notice the double bang operator (i.e. `!!`) in front of `stars`. (Well, actually there is no “double bang operator”. Were just using the bang operator twice.)
The first bang operator will coerce the value of `stars` into a boolean and then perform a NOT operation. If `stars` is `0`, then `!stars` will produce `true`.
Then we perform a second NOT operation, so if `stars` is 0, `!!stars` would produce `false`. Exactly what we want.
If youre not a fan of `!!`, you can also force a boolean like this (which I find a little wordy).
```
{Boolean(stars) && (
```
Or simply give a comparator that results in a boolean value (which some might say is even more semantic).
```
{stars > 0 && (
```
#### A word on strings
Empty string values suffer the same issue as numbers. But because a rendered empty string is invisible, its not a problem that you will likely have to deal with, or will even notice. However, if you are a perfectionist and dont want an empty string on your DOM, you should take similar precautions as we did for numbers above.
### Another solution
A possible solution, and one that scales to other variables in the future, would be to create a separate `shouldRenderStars` variable. Then you are dealing with boolean values in your logical AND.
```
const shouldRenderStars = stars > 0;
```
```
return (
<div>
{shouldRenderStars && (
<div>
{'⭐️'.repeat(stars)}
</div>
)}
</div>
);
```
Then, if in the future, the business rule is that you also need to be logged in, own a dog, and drink light beer, you could change how `shouldRenderStars` is computed, and what is returned would remain unchanged. You could also place this logic elsewhere where its testable and keep the rendering explicit.
```
const shouldRenderStars =
stars > 0 && loggedIn && pet === 'dog' && beerPref === 'light`;
```
```
return (
<div>
{shouldRenderStars && (
<div>
{'⭐️'.repeat(stars)}
</div>
)}
</div>
);
```
### Conclusion
Im of the opinion that you should make best use of the language. And for JavaScript, this means using conditional ternary operators for `if/else`conditions and logical AND operators for simple `if` conditions.
While we could just retreat back to our safe comfy place where we use the ternary operator everywhere, you now possess the knowledge and power to go forth AND prosper.
--------------------------------------------------------------------------------
作者简介:
Managing Editor at the American Express Engineering Blog http://aexp.io and Director of Engineering @AmericanExpress. MyViews !== ThoseOfMyEmployer.
----------------
via: https://medium.freecodecamp.org/conditional-rendering-in-react-using-ternaries-and-logical-and-7807f53b6935
作者:[Donavon West][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://medium.freecodecamp.org/@donavon
[1]:https://unsplash.com/photos/pKeF6Tt3c08?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[2]:https://unsplash.com/search/photos/road-sign?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[3]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators