Skip to content

Commit

Permalink
more progress on things
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Mar 1, 2024
1 parent d26f480 commit 57f4bcd
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 55 deletions.
4 changes: 2 additions & 2 deletions exercises/04.components/01.problem.function/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ to understand them. We'll get to custom components in the next steps.

📜 Read more

- [https://react.dev/learn/javascript-in-jsx-with-curly-braces](https://react.dev/learn/javascript-in-jsx-with-curly-braces)
- [https://kentcdodds.com/blog/what-is-jsx](https://kentcdodds.com/blog/what-is-jsx)
- [JavaScript in JSX with Curly Braces](https://react.dev/learn/javascript-in-jsx-with-curly-braces)
- [What is JSX?](https://kentcdodds.com/blog/what-is-jsx)
3 changes: 3 additions & 0 deletions exercises/04.components/02.problem.raw/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ function someFunction(props) {
return // some jsx
}
```

So let's move from calling `message` directly to calling it through
`React.createElement`.
11 changes: 11 additions & 0 deletions exercises/04.components/03.problem.jsx/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,14 @@ element = <lower_snake_case /> // React.createElement('lower_snake_case')

Now let's refactor your function to a name that will make it possible to call it
by using it as a JSX component.

The most common approaches you'll find in the wild are to have the name of the
component capitalized:

```tsx
element = <Capitalized /> // React.createElement(Capitalized)
```

Sometimes you'll see the property access syntax as well.

Let's go refactor so we can use our componets as JSX!
36 changes: 35 additions & 1 deletion exercises/04.components/03.solution.jsx/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,38 @@ equivalent:
<Alert children="Something went wrong!" />
```

We'll learn more about that next.
Our `Message` component uses the "special" and implicit `children` prop. It's
special because it means we can do this:

```tsx
element = <Message>Hello World</Message>
// is functionally equivalent to:
element = <Message children="Hello World" />
```

And you can put JSX in the children prop with either syntax as well:

```tsx
element = (
<Message>
<span>Hello</span> <span>World</span>
</Message>
)
// is functionally equivalent to:
element = <Message children={[<span>Hello</span>, ' ', <span>World</span>]} />
```

📜 [Learn more about passing JSX as `children`](https://react.dev/learn/passing-props-to-a-component#passing-jsx-as-children).

But we don't have to use the `children` prop, we can call it whatever we want.
So you could also do:

```tsx
element = <Message greeting={[<span>Hello</span>, ' ', <span>World</span>]} />
```

The only thing that's special about the `children` prop is that it's implicit
in JSX.

And sometimes using something other than the `children` prop can be really
useful, but we'll get to that in a future workshop.
23 changes: 1 addition & 22 deletions exercises/04.components/04.problem.props/README.mdx
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
# Props

👨‍💼 You are the commander of your component's API. The API for your component is
"props" which is the object your component function accepts as an argument. For
example, our `Message` component uses the "special" and implicit `children`
prop. It's special because it means we can do this:

```tsx
element = <Message>Hello World</Message>
// is functionally equivalent to
element = <Message children="Hello World" />

// and this:
element = (
<Message>
<span>Hello</span> <span>World</span>
</Message>
)
// is functionally equivalent to
element = <Message children={[<span>Hello</span>, ' ', <span>World</span>]} />
```

But we don't have to use the `children` prop, we can call it whatever we want.
And sometimes using something other than the `children` prop can be really
useful.
"props" which is the object your component function accepts as an argument.

So now, we're going to use a `Calculator` component that can display an
equation and it's solution, like so:
Expand Down
2 changes: 1 addition & 1 deletion exercises/04.components/FINISHED.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Custom Components

Great job! Now you've got a good handle on what it takes to create a custom
👨‍💼 Great job! Now you've got a good handle on what it takes to create a custom
component with React. And it's not a surface-level understanding either. You
understand how it works under the hood which will be critical to your experience
building custom components going forward. Great job!
20 changes: 19 additions & 1 deletion exercises/04.components/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,25 @@ these functions "components" and they have some special properties.
Components are functions which accept an object called "props" and return
something that is renderable (more React elements, strings, `null`, numbers,
etc.). To be clear, this is _the_ definition of a React component. That's all it
is. So I'll say it again:
is. So I'll say it
[again](https://twitter.com/kentcdodds/status/1763606427028136131):

> Components are functions which accept an object called "props" and return
> something that is renderable
Here's an example of that:

```tsx
function Greeting(props) {
return <h1>Hello, {props.name}</h1>
}
```

Then that component can be used like this:

```tsx
<Greeting name="World" />
```

Just like previous exercises, we're going to ease into this syntax so you have a
solid foundational understanding of how this works.
4 changes: 2 additions & 2 deletions exercises/05.typescript/FINISHED.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# TypeScript

Awesome work. TypeScript is a must in this industry and using it with React is
fairly straightforward.
👨‍💼 Awesome work. TypeScript is a must in this industry and using it with React
is fairly straightforward.
45 changes: 26 additions & 19 deletions exercises/05.typescript/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ you plan making maintainable. As you're working with TypeScript and getting
angry at all the red squiggles it puts in your code, keep this in mind:

> TypeScript is not making your life terrible. It's just showing you how
> terrible your life already is. – Kent C. Dodds
> terrible your life already is. – [Kent C. Dodds](https://twitter.com/kentcdodds/status/1763606063394496633)
You can think of TypeScript as that brutally honest friend who isn't afraid to
tell you about the spinach in your teeth. It's not the friend's fault that
you've got spinach in your teeth. It's your fault. You should be thanking
TypeScript, not cursing it.
You can think of TypeScript as that
[brutally honest friend](https://twitter.com/kentcdodds/status/1715562350835855396)
who isn't afraid to tell you about the spinach in your teeth. It's not the
friend's fault that you've got spinach in your teeth. It's your fault. You
should be thanking TypeScript, not cursing it.

Remember, in exercise 4 we learned what a React component is:
Remember, in exercise 4 we learned
[what a React component](https://twitter.com/kentcdodds/status/1763606427028136131)
is:

> Components are functions which accept an object called "props" and return
> something that is renderable
Expand Down Expand Up @@ -88,12 +91,12 @@ function Message(props: { children: React.ReactNode }) {
return <div className="message">{props.children}</div>
}

// and you can destructure as well:
// and you can destructure as well (this is what I do most of the time):
function Message({ children }: { children: React.ReactNode }) {
return <div className="message">{children}</div>
}

// mix-and-match (this is what I do most of the time):
// mix-and-match:
type MessageProps = { children: React.ReactNode }
function Message({ children }: MessageProps) {
return <div className="message">{children}</div>
Expand All @@ -111,17 +114,21 @@ experienced or want to focus on it. You can do this like so:
```typescript
// @ts-expect-error TypeScript is complaining about this next line.
// Something about magic not existing.
// I don't know how to fix this right now... Come back later.
// I don't know how to fix this right now and AI Assistants were unhelpful...
// Come back later.
make.magic()
```

Unfortunately, there are some things that TypeScript cannot do for you

👨‍💼 Note also, we're moving from the `*.html` files to `*.tsx` files. This is
more real-world and also your editor likely supports TypeScript better within
TypeScript files rather than HTML files. From here on out, the `index.tsx` file
will be loaded onto the page automatically. We'll also get live reload of the
browser as we save changes which will be quite nice. The workshop app is a
little magical, but you'll find
`ReactDOM.createRoot(rootElement).render(element)` calls in each of the files,
just like we were doing in the previous exercises.
Don't worry if you struggle with TypeScript at first, the more you use it, the
better you'll get at it, just like anything else.

<callout-info>
Note: we're moving from the `*.html` files to `*.tsx` files. This is more
real-world and also your editor likely supports TypeScript better within
TypeScript files rather than HTML files. From here on out, the `index.tsx`
file will be loaded onto the page automatically. We'll also get live reload of
the browser as we save changes which will be quite nice. The workshop app is a
little magical, but you'll find
`ReactDOM.createRoot(rootElement).render(element)` calls in each of the files,
just like we were doing in the previous exercises.
</callout-info>
87 changes: 80 additions & 7 deletions exercises/06.styling/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,69 @@ There are two primary ways to style react components
1. Inline styles with the `style` prop
2. Regular CSS with the `className` prop

**About the `style` prop:**
Before we get into those, you need to know something about element properties
and HTML attributes.

- In HTML you'd pass a string of CSS:
## Element properties and HTML attributes

In HTML, you have elements and attributes. For example, the `div` element has a
`class` attribute:

```html
<div class="my-class"></div>
```

In the DOM, the `div` element has a `className` property:

```html
<div style="margin-top: 20px; background-color: blue;"></div>
<div id="my-div" class="my-class"></div>
<script>
const myDiv = document.getElementById('my-div')
console.log(myDiv.class) // undefined
console.log(myDiv.className) // "my-class"
</script>
```

- In React, you'll pass an object of CSS:
In JSX, you use the property name rather than the attribute name:

```tsx
<div className="my-class" />
```

This applies to a number of other attributes as well. For example, `for` in HTML
is `htmlFor` in DOM (and JSX). Others include `tabindex` and `readonly` (which
are, respectively, `tabIndex` and `readOnly` in JSX).

Most differences between HTML attributes and JSX props are due to the fact that
props are a reference to "properties" not "attributes", so understanding the
difference is handy!

## Inline styles

Inline styles are set differently in JSX from HTML as a result of how they are
applied to the DOM. In HTML, you'd pass a string of CSS, but you access it as an
object in the DOM:

```html
<div id="my-div" style="margin-top: 20px; background-color: blue;"></div>
<script>
const myDiv = document.getElementById('my-div')
console.log(myDiv.style.marginTop) // "20px"
console.log(myDiv.style.backgroundColor) // "blue"
</script>
```

As a result, in JSX, you pass an object of CSS rather than a string:

```tsx
<div style={{ marginTop: 20, backgroundColor: 'blue' }} />
```

This actually makes them much easier to work with. Though the style prop has
some significant limitations (like lack of media queries and pseudo-selectors),
so it's not always the best choice.

<callout-warning class="aside">
Note that in react the `{{` and `}}` is actually a combination of a JSX
expression and an object expression. The same example above could be written
like so:
Expand All @@ -28,12 +77,36 @@ const myStyles = {marginTop: 20, backgroundColor: 'blue'}
<div style={myStyles} />
```

</callout-warning>

Note also that the property names are `camelCased` rather than `kebab-cased`.
This matches the `style` property of DOM nodes (which is a
[`CSSStyleDeclaration`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration)
object).

**About the `className` prop:**
## Class names

The most common mechanism for styling web applications is through the use of CSS
and class names.

As mentioned earlier, in HTML, you apply a class name to an element with the
`class` attribute. In JSX, you use the `className` prop:

```tsx
<div className="my-class" />
```

Then you'll load a CSS file onto the page:

As we discussed earlier, in HTML, you apply a class name to an element with the
`class` attribute. In JSX, you use the `className` prop.
```html
<link rel="stylesheet" href="styles.css" />
```

And that can contain the styles for `.my-class`:

```css
.my-class {
margin-top: 20px;
background-color: blue;
}
```

0 comments on commit 57f4bcd

Please sign in to comment.