DEV Community

Stefan Judis
Stefan Judis

Posted on • Originally published at stefanjudis.com

A React "if component"

After using Vue and Angular.js (I used the first version of Angular when it came out) for many years, I have to say that I always enjoyed the simplicity of using v-if and ng-if to render child components conditionally.

Now I'm writing React primarily and honestly I'm bothered by the constant use of ternary operators when dealing with conditionally rendered components.

function SomeComponent({condition}) {
  return <div>
    { condition ? <span>Yes it is true!</span> : null }
  </div>
}
Enter fullscreen mode Exit fullscreen mode

It's not a big deal, and there are many different ways to render boolean-dependent components, but I find myself writing code such as the above repeatedly.

Today I read 7 Ways of Achieving Conditional Rendering in React, and it included a handy snippet that I'll adopt from now on.

A conditional if component

I can't say that I didn't consider abstracting the ternary operators away, but somehow I never took it into practice. Fernando Doglio's article now moved me over the line to adopt a nicer pattern. Say hi to the functional if component.

function IF({children, condition}) {
  if (condition) {
    // render children if the condition is truthy
    return children;
  }

  return null;
}

/**
 * Use the component as follows:
 *
 * <IF condition={condition}>
 *   <Greeter username={user.name} />
 * </IF>
 */
Enter fullscreen mode Exit fullscreen mode

It's seven lines of code and this tiny component can be brought into any React project as handy utility. Much better! Thank you Fernando!

Top comments (6)

Collapse
 
stereoplegic profile image
Mike Bybee • Edited

I personally think ternaries are fine, but expanding on your solution:

By adding a third else = null prop (and return else instead of return null), you can default to null while allowing for an actual value on the other side of the ternary e.g.

function IF({children, condition, else = null}) {
  if (condition) {
    // render children if the condition is truthy
    return children;
  }

  return else;
}

/**
 * Use the component as follows:
 *
 * <IF condition={condition}>
 *   <Greeter username={user.name} />
 * </IF>
 *
 * With 'else' prop, equivalent to
 * {condition ? <Greeter  username={user.name} /> : <LoginButton />}
 *
 * const renderElse = () => <LoginButton />
 * <IF condition={condition} else={renderElse}>
 *   <Greeter username={user.name} />
 * </IF>
 *
 *
 */
Enter fullscreen mode Exit fullscreen mode

You could even take it further with another prop, an array of objects in the shape of {extraCondition, extraReturn}, for else if scenarios (that's going to take too much typing to give an example of the additional logic on my phone, but I hope you get the gist).

Collapse
 
shadowtime2000 profile image
shadowtime2000

May also be pretty nice to use React.memo on it, just for performance.

Collapse
 
shadowtime2000 profile image
shadowtime2000
import { memo } from "react";

function If({ children, condition }) {
    return condition ? children : null;
}

export default memo(If, (props, oldProps) => props.condition === oldProps.condition);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
koire profile image
Koire

This is a really good expression of it.
I've been trying to do something very similar since we have something like

<Title> {newAccount ? "newtitle": "oldtitle"}</Title>
Enter fullscreen mode Exit fullscreen mode

but we have a few ways for newAccount to be true
something like

<IF condition={isNewAccount}> This is a new account</IF>
Enter fullscreen mode Exit fullscreen mode

is a start

Collapse
 
josdejong profile image
Jos de Jong • Edited

I do like this solution. We've used this in the past but reverted this again soon: it led to performance issues.

Unlike the ternary operator a ? b : c or &&, this <IF>...</IF> component will always create and render its inner contents (children), and in case the condition is false, the rendered children is only ignored by <IF> in the end. That can be very expensive.

Collapse
 
griffadev profile image
George Griffiths

This feels like going back around to html templating languages like handlebars or nunjucks or ejs and I don't hate that