There are some at Facebook who have argued against returning null when rendering an XHP element. In fact, it’s actually against Facebook’s standards now. Personally, I prefer to structure my code to return null in XHP, but there definitely are pros and cons. I’ll cover the situations in which you might want to return null and what the alternatives could be, and then you can decide for yourself.

First, let me clarify that when I say returning null, I actually mean returning an empty element from your :x:element-extended class – basically meaning you don’t want it to render into anything. So when would you return null from an XHP element? Well, often times it is when the element should only conditionally exist. Let’s contrive a simple example.

class :post:edit-link extends :x:element {  attribute Post post @require;  protected function render() {    $post = $this->getAttribute(‘‘post’’);    if ($post->author != get_loggedin_user() && !user_is_admin()) {      return ;    }    return <a href={“/post/{$post->id}/edit”}>Edit</a>;  }}class :blog:post extends :x:element {  attribute Post post @required;  protected function render() {    $post = $this->getAttribute(‘‘post’’);    return      <div class="post">        <div class="title">{$post->title}</div>        {$post->content}        <div class="links">          <post:permalink post={$post} />          ·          <post:comment-link post={$post} />          ·          <post:edit-link post={$post} />        </div>      </div>;  }}

So in this scenario, we have which will conditionally return a link to edit the post if you are the author. However, if you are not the author you’ll see a floating · underneath each blog post. We cannot tell without rendering if it will return content or not, so there’s no way to conditionally control the last · from inside :blog:post::render(). This is the primary reason some people feel rendering null in XHP is bad practice. To remove the null rendering from we’ll have to take that check and put it somewhere else. We could just move it into :blog:post::render() – and every other place is instantiated – but ideally you’d want a better abstraction than that. So let’s create a static method that will make the check for us. Here’s our code now:

class :post:edit-link extends :x:element {  attribute Post post @require;  public static function generateInstance(Post $post) {    if ($post->author == get_loggedin_user()   user_is_admin()) {      return <post:edit-link post={$post} />;    }    return null;  }  protected function render() {    $post = $this->getAttribute(‘‘post’’);    return <a href={“/post/{$post->id}/edit”}>Edit</a>;  }}class :blog:post extends :x:element {  attribute Post post @required;  protected function render() {    $post = $this->getAttribute(‘‘post’’);    $editLink = :post:edit-link::generateInstance($post);    if ($editLink) {      $editLink =                  ·          {$editLink}        ;    }    return      <div class="post">        <div class="title">{$post->title}</div>        {$post->content}        <div class="links">          <post:permalink post={$post} />          ·          <post:comment-link post={$post} />          {$editLink}        </div>      </div>;  }}

So now the code is a little less clean, though not by much, but we’ve introduced an important hole into the system. If anyone forgets to instantiate in this special manner, the security check will not happen and the link will be rendered. In our contrived example it’s probably not a big deal, but this is not a safe pattern. We’ve introduced a possible code path that will skip our security check, and that should throw red flags like no tomorrow. Let’s take a look at alternative solutions to this problem that keep the logic encapsulated within :post:edit-link::render(). First, I’m a firm believer in CSS and the fact that it can solve a lot of problems if you know how to use it.

class :blog:post extends :x:element {  attribute Post post @required;  protected function render() {    $post = $this->getAttribute(‘‘post’’);    return      <div class="post">        <div class="title">{$post->title}</div>        {$post->content}        <div class="links">          <post:permalink post={$post} />          ·           <post:comment-link post={$post} />          ·           <post:edit-link post={$post} />        </div>      </div>;  }} // CSS .middot + .middot,.middot:first-child,.middot:last-child {  display: none;}

By wrapping the middots in an element, we can target them with CSS and hide any middots that don’t have elements between them, or are trailing at the beginning or end. Unfortunately if you need to support IE6 or basic mobile phones this isn’t going to work. Or maybe you just aren’t a fan of the extra DOM nodes. That’s fine, there’s another way we can handle this. In my post The Difference Between :x:element and :x:primitive I talked about the different rendering processes for each type of XHP class. :x:primitives render after their :x:element children. This means that you actually can write an XHP element that will wait for its children to render before rendering itself, and we can use that to fix our · problem.

class :middot-spacer extends :x:primitve {  protected function stringify() {    $children = $this->getChildren();    if (!$children) {      return ‘’’’;    }    $split = {array_shift($children)};    while(!empty($children)) {      $split->appendChild(                  ·          {array_shift($children)}              );    }    return :xhp:renderChild($split);  }}

This behaves the same way in terms of rendering order as if were <div>, so you won’t get surprised by any edge cases. Using either of the last two examples should solve 99.9% of cases (I leave 0.1% for things I can’t think of, but if you can think of any please let me know). Even complicated interactions, say for example, a component that takes a list of links (that may render null) and if the list is greater than some threshold, converts that list into a drop down menu. You can still use the :x:primitive solution to handle those cases. If there is some reason why you still need/want to know if your component will render null outside of the component itself, you could always implement a method to tell you, and use that method inside render().

class :post:edit-link extends :x:element {  attribute Post post @require;  public function willRenderNULL() {    $post = $this->getAttribute(‘‘post’’);    return $post->author != get_loggedin_user() && !user_is_admin();  }  protected function render() {    $post = $this->getAttribute(‘‘post’’);    if ($this->willRenderNULL()) {      return ;    }    return <a href={“/post/{$post->id}/edit”}>Edit</a>;  }}

There should be very very few cases that these solutions won’t cover, but you might wonder then, why Facebook has made it a rule of thumb not to return null? I think it has to do with the fact that we traditionally urge against extending :x:primitive (to simplify engineers’ need to understand the inner-workings of XHP) and we also automatically reference elements in JS, which means if the component doesn’t render there might be JS errors. An edge case for sure, and something that isn’t difficult to get around, but it’s one more thing to think about when building. Really when it boils down to it, I prefer to keep my logic consolidated and have a very hard time with the idea that there is a code path that could violate security checks. I suppose it all depends on how well you know your system and where you want the potential problems to arise.

You can continue reading this article on Code Before The Horse, where it was originally posted.