Appearance
Lists, keys, and conditionals without directives
Vue gave you
v-if/v-for. React gives you JavaScript. Same problems, fewer magic attributes.
Conditionals
tsx
function Inbox({ messages }: { messages: Message[] }) {
if (messages.length === 0) {
return <p>Inbox zero. Nice.</p>
}
return (
<ul>
{messages.map((m) => (
<li key={m.id}>{m.subject}</li>
))}
</ul>
)
}Ternary inline when it's small:
tsx
{isOpen ? <Dropdown /> : null}Keys - same rules as Vue, same pain when ignored
tsx
{items.map((item) => (
<Row key={item.id} item={item} />
))}Comments for the code above:
keyhelps React match instances across re-renders- Stable IDs > array index (index is OK for static lists that never reorder)
- Changing a
keyremounts the component - useful trick to reset state
Remount with key (underrated)
Vue folks sometimes use :key on a component to force reset. Same in React:
tsx
<UserEditor key={userId} userId={userId} />When userId changes, React throws away the old tree and mounts fresh. Local form state resets. Cleaner than a pile of useEffect sync code.
Filtering / sorting
Do it in JS before JSX - don't invent template filters:
tsx
const visible = todos.filter((t) => (showDone ? true : !t.done))
return (
<ul>
{visible.map((t) => (
<li key={t.id}>{t.text}</li>
))}
</ul>
)As you can see - prepare data, then render. Keeps JSX readable.
Empty states and loading
I like early returns for the "not ready" branches:
tsx
if (isLoading) return <Spinner />
if (error) return <ErrorMessage error={error} />
if (!data) return null
return <Results data={data} />Reads top-to-bottom. Nested ternaries in JSX get ugly fast.
Next: forms - controlled inputs, the React default.
Enjoy!