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, we’ll explore a few alternatives. But be warned that some come with their own gotchas, if you’re not careful. ### Ternary vs if/else Let’s 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. Here’s a Stateless Function Component (SFC) that does just that. ``` const MyComponent = ({ name }) => { if (name) { return (
Hello {name}
); } return (
Please sign in
); }; ``` Pretty straightforward. But we can do better. Here’s the same component written using a conditional ternary operator. ``` const MyComponent = ({ name }) => (
{name ? `Hello ${name}` : 'Please sign in'}
); ``` 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 `
` markup. 🎉 ### Ternary vs Logical AND As you can see, ternaries are wonderful for `if/else` conditions. But what about simple `if` conditions? Let’s 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}) => (
Hello {name} {isPro ? '🏆' : null}
{stars ? (
Stars:{'⭐️'.repeat(stars)}
) : null}
); ``` 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. Here’s the same code written using a logical AND. ``` const MyComponent = ({ name, isPro, stars}) => (
Hello {name} {isPro && '🏆'}
{stars && (
Stars:{'⭐️'.repeat(stars)}
)}
); ``` 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. That’s the gotcha that I was referring to above. Here’s 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 wasn’t 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 won’t render. Say, like a value of `false`. There are a few ways that we can accomplish this. Let’s try this instead. ``` {!!stars && (
{'⭐️'.repeat(stars)}
)} ``` Notice the double bang operator (i.e. `!!`) in front of `stars`. (Well, actually there is no “double bang operator”. We’re 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 you’re 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, it’s not a problem that you will likely have to deal with, or will even notice. However, if you are a perfectionist and don’t 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 (
{shouldRenderStars && (
{'⭐️'.repeat(stars)}
)}
); ``` 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 it’s testable and keep the rendering explicit. ``` const shouldRenderStars = stars > 0 && loggedIn && pet === 'dog' && beerPref === 'light`; ``` ``` return (
{shouldRenderStars && (
{'⭐️'.repeat(stars)}
)}
); ``` ### Conclusion I’m 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