Introduction to JSX and Components

This video starts by setting up a react app using Vite. Ignore this part and just start watching from the JSX chapter. There's also a section on CSS that you can ignore.

The JSX section starts with an App.jsx file that looks like this:

function App() {
return (
<h1>Hello</h1>
)
}

export default App
function App() {
return (
<h1>Hello</h1>
)
}

export default App
function App() {
return (
<h1>Hello</h1>
)
}

export default App
function App() {
return (
<h1>Hello</h1>
)
}

export default App

This is similar to a page in Next.js, so follow along with my examples but use the page.tsx component.

JSX and TSX

JSX is a syntax extension for JavaScript, which means that it gives us new ways to write code that are not part of the JavaScript language. It's like adding new vocabulary or rules to an existing language, so we can express more complex ideas more easily.

With JSX, we can write HTML-like markup inside a JavaScript file. TSX (TypeScript JSX) is the same thing but with in a TypeScript file.

some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}
some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}
some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}
some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}

JSX and TSX is eventually transpiled into JavaScript, so the above code is transpiled into something like this:

some-component.js
import { jsx } from "react/jsx-runtime";
jsx("div", null,
jsx("h1", { className: "text-bold" }, "Hello"),
jsx("h2", null, "World")
)
some-component.js
import { jsx } from "react/jsx-runtime";
jsx("div", null,
jsx("h1", { className: "text-bold" }, "Hello"),
jsx("h2", null, "World")
)
some-component.js
import { jsx } from "react/jsx-runtime";
jsx("div", null,
jsx("h1", { className: "text-bold" }, "Hello"),
jsx("h2", null, "World")
)
some-component.js
import { jsx } from "react/jsx-runtime";
jsx("div", null,
jsx("h1", { className: "text-bold" }, "Hello"),
jsx("h2", null, "World")
)

Which is just normal JavaScript code that we can run in node, or the browser, or anywhere we can install and run the react library.

When the jsx function is called, it returns a JavaScript object that contains all the information about the JSX element we created. A simplified version looks like this:

{
type: 'div',
props: {
children: [
{
type: 'h1',
props: {
className: 'text-bold',
children: 'Hello'
}
},
{
type: 'h2',
props: {
children: 'World'
}
}
]
}
}
{
type: 'div',
props: {
children: [
{
type: 'h1',
props: {
className: 'text-bold',
children: 'Hello'
}
},
{
type: 'h2',
props: {
children: 'World'
}
}
]
}
}
{
type: 'div',
props: {
children: [
{
type: 'h1',
props: {
className: 'text-bold',
children: 'Hello'
}
},
{
type: 'h2',
props: {
children: 'World'
}
}
]
}
}
{
type: 'div',
props: {
children: [
{
type: 'h1',
props: {
className: 'text-bold',
children: 'Hello'
}
},
{
type: 'h2',
props: {
children: 'World'
}
}
]
}
}

Then that code might eventually end up as HTML that we see in the browser:

<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>
<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>
<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>
<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>

It seems like JSX is just a way to write HTML looking code in our JavaScript files, but it's actually a way to write JavaScript that eventually gets translated into HTML.

We write this:
some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}
some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}
some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}
some-component.tsx
function SomeComponent() {
console.log("Some Component")
return (
<div>
<h1 className="text-bold">Hello</h1>
<h2>World</h2>
</div>
)
}
We end up with this:
<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>
<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>
<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>
<div>
<h1 class="text-bold">Hello</h1>
<h2>World</h2>
</div>

The point of all this is so that we can stay in JavaScript and do everything in JavaScript and never actually touch an HTML file. However, the way we describe a web page is with HTML. Everything we want the user to see eventually gets translated into HTML and CSS.

JavaScript in JSX

So like I said, this is js, so you can inject js into jsx.

Not rendered as JS:

<p>6 + 9</p>
<p>6 + 9</p>
<p>6 + 9</p>
<p>6 + 9</p>

Rendered as JS:

<p>{6 + 9}</p>
<p>{6 + 9}</p>
<p>{6 + 9}</p>
<p>{6 + 9}</p>

Try adding more JS things to your markup:

return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
</div>
)
return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
</div>
)
return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
</div>
)
return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
</div>
)

A component couples the UI logic and markup together in the same file. So instead of separating your js and html into separate files, it all goes in the same file and we split the app into separate components instead.

Rendering logic and markup live together in the same place—components.

More components and Child components

If we want to create another component, we can just create a new function with an uppercase character that returns markup:

function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}
function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}
function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}
function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}

Component Files

It's common to put each component in their own file, even if they're very small like this one.

Create a new file with the kebab-named version of your component's name and put it in there:

some-new-component.jsx
some-new-component.jsx
some-new-component.jsx
some-new-component.jsx

export using esmodules synax:

some-new-component.tsx
export default function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}
some-new-component.tsx
export default function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}
some-new-component.tsx
export default function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}
some-new-component.tsx
export default function SomeNewComponent() {
return (
<h1>Some Markup</h1>
)
}

import using esmodules synax:

page.tsx
import SomeNewComponent from './some-new-component'
page.tsx
import SomeNewComponent from './some-new-component'
page.tsx
import SomeNewComponent from './some-new-component'
page.tsx
import SomeNewComponent from './some-new-component'

Then include it in the markup:

page.tsx
function Page() {
return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
<SomeNewComponent />
</div>
)
}
page.tsx
function Page() {
return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
<SomeNewComponent />
</div>
)
}
page.tsx
function Page() {
return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
<SomeNewComponent />
</div>
)
}
page.tsx
function Page() {
return (
<div className="App">
<h1 className="heading">Hello</h1>
<h2>World</h2>
<h3>{new Date().toString()}</h3>
<SomeNewComponent />
</div>
)
}

The Rules of JSX and TSX

Return a single root element, div or empty tag <>

some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)

All tags must close, so you can <img></img> or self close tags like <img />

some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)

This is js, not html, so any reserved word in JavaScript has a different name here like className instead of class

some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)
some-component.jsx
return (
<div>
<h1 className="header">Hello</h1>
<h2>World</h2>
<img className="image" src="https://picsum.photos/200" alt="random"></img>
</div>
)