As a professional developer you are forced to stay up to date with the latest trends in technology. This year I've added Svelte to my bucket list as a new framework to learn.
While researching Svelte I was surprised by the way they handle condition rendering.
Take a look at this example found in their docs:
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}
Everything is neatly wrapped with if clause and separated from normal flow.
After a quick prototyping I present to you the most powerful component I have ever written, an IF component.
const IF = ({ condition, children }) => {
if (!condition) return null;
return <>{children}</>;
};
By offloading condition into a separate component this will improve code cleanness and readability by quite a margin (for free).
Let’s imagine the Svelte example in our React app. It would go something like this:
…
return (
<>
{user.loggedIn && <button>Log out</button>}
</>
);
...
This is not an end of the world issue when you have just one condition but as our apps grow, so do the conditions.
Take a look at the same component now refactored to use IF:
…
return (
<IF condition={user.loggedIn}>
<button>Log out</button>
</IF>
);
...
Now it’s easier to track down conditions and debug faulty ones, plus the code looks way cleaner now that conditions are gone from JSX.
Hope you found this helpful ❤️
Top comments (38)
Nice one! If you're interested in exploring other frameworks, in SolidJS you have:
...which you can use like:
I find really neat.
How to write this type of code(like second) in Dev Community post please help
Do you mean syntax highlighting? If so, then like this:
It's just Mardown compatible with Github.
Yes but how please share image details
Take a look at this official markdown guide:
markdownguide.org/extended-syntax/
@chetan_atrawalkar just surround your code with the following:
Thank you❤️
hi
Nice tip. Thank you ❤️
Nice, I do something similar - it's also cool to add
then
andelse
as props. I also do this with switch:I use it like this:
I've tried it, it's pretty neat but do you know how to limit type with React context? Ie to make Typescript do not complain about missing props
stackblitz.com/edit/react-ts-6ynx8...
I tried the link but didn't see any lint issues etc, what is it complaining about?
Nice, but you are missing Default case when no other matches
Nope, I just called it CaseElse (my project has a ton of things called DefaultXYZ so it doesn't scan well).
Oh wow this looks interesting. Thank you for sharing :)
Your approach has an issue: the children are still being rendered, they’re just not being displayed. So if you have a component that, say, makes a network request when it mounts, that’s still going to happen, which is likely not what you want.
This is wrong. It's true that the elements are still constructed, but nothing is mounted and since React only goes in top-bottom the non-rendering / non-mounted children will never be looked at.
Look at this example.
What you'll see in the console is:
(Note there is no
false - displayed
shown.)So there shouldn't be any such thing as a network request (which anyway shouldn't appear there, because these things are side-effects and, e.g.,
useEffect
would only be called on mounted components anyway).The only issue with this approach is that you construct more objects (i.e., React elements) than you would otherwise. This becomes only an issue when you have a larger render tree spawning from there.
Exactly 🙂 Thank you for detailed clarification.
No issue with extra elements in Solid, no matter how big the app gets. Check it out!
solidjs.com
Interesting. Can you explain further? They are rendered by the parent component but the 'IF' component just controls whether they are displayed or not?
Correct. ‘IF’ and the child are rendered from the same place. The ‘children’ prop is just a reference, is not actual call site. To actually prevent it from being rendered, you would want to call the conditionally rendered component from the ‘IF’.
I'm not sure if this is a good way to test but I tried testing it by creating a component that logs to the console when it renders and it looks like that code never ran.
Link to CodePen: codepen.io/hedwardd/pen/xxdOpxy?ed...
Could it have something to do with it being a functional component?
Exactly, this will actually add the child node to the tree and perform any effects for example. You can avoid this by using render props, but that kinda defeats the purpose.
Does it? Now I'm confused. If you look at the CodePen I created, the effects don't seem to run (unless I'm misunderstanding something)
Actually it shouldn't run. I've created a codesadbox for you guys to check out where you can see both functional and class based components.
Here is the link:
codesandbox.io/s/nice-wiles-cwfi6?...
IMO there is no need to create an
<IF>
component. For most simple cases, ternary operator<condition> ? <if-true> : <if-false>
or simple boolean operators&&
and/or||
will do the job; for something more complex, it would be better to create an additional function to render it. If we want to render it directly in place and we have many conditions/components to check, there is a new Javascriptdo
expression (tc39/proposal-do-expressions) that is in stage 1 of the TC39 process and it will solve such problems by using some native syntax like:We can already use it by using Babel plugin @babel/plugin-proposal-do-expressions.
Figured I’d share one of the first use cases I found for this and it’s one I believe could be helpful to others. That’s in hydrating state with React Router useHistory state in the event of a browser refresh.
When calling the component you’d need to add a handleRestore function that took the fallbackValue and setter function as parameters.
It works well with React Router useHistory state that persists during browser refresh.
This is a question, not a critique, is it not necessary to check for the existence of the conditional variable if you use the NOT operator?
Fwiw, great post! Definitely will use this as inspiration for some component refactoring on my current project.
Thanks!!
Hello, no actually you don't have to every falsy value is considered as false.
Thanks! That’s super helpful to know!
To each their own, but I argue this is a unnecessary abstraction. It’s like creating an add() function that adds numbers when you can do a + b in code.
For me honestly it was more of a stylistic choice. I like when my jsx resembles closely HTML
this is pretty genius. good job. WIll be using. thanks.
Thank you ❤️
Personally I swear by jsx-control-statements
I use it pretty much every day for conditional rendering
I wasn't aware of this. Thanks for sharing 🙂
hi
👋