Avoid render of the children in the Stencil.js components

If you are used to React.js components, you know that you are deciding to show or not the children elements. And if you don't put { children } in your output, there will be nothing on the page, plus the components themselves are not going to run their logic.

Stencil components are web-components. And web-components should behave just like any HTML-element — if there is something inside it, it's in the DOM. And if there are other web-components, they will run their own logic regardless of the parent's state.

There are a few closed issues about it like this one or that one. And I think that the Stencil guys are not going to fix that behavior.

The proposed solution is to use shadow: true in the component decorator. And yes, that will hide the content but the logic will still be processed as a web-components.

In my case, I was creating a component that is checking is the user authorized and if it is, show the content otherwise — show the login form.

<app-auth> 
  <stencil-router> 
    <PrivateRoute ... /> 
    <stencil-route ... /> 
    ... 
  </stencil-router> 
</app-auth>

As you can see, I have the router inside the component, and it will make all the redirections before the user is authorized. Not acceptable.

I've tried a lot of different things, and only two worked out:

  • Additional check inside the main component, but that didn't look right, since we are spreading the logic to the components not responsible for the check:
<app-auth> 
  { AppStore.user.uid && 
    <stencil-router ... /> 
  } 
</app-auth>
  • Passing the children as an attribute:
<app-auth content={( 
  <stencil-router ... /> 
)} />

And it looks like the latter is the only acceptable way for me to do that.