Skip to content

Fixed typo #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
9 changes: 5 additions & 4 deletions lessons/action-creators.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,23 @@ export default function changeLocation(location) {
changeAnimal.js

```javascript
export default function changeAnimal(location) {
return { type: "CHANGE_ANIMAL", payload: location };
export default function changeAnimal(animal) {
return { type: "CHANGE_ANIMAL", payload: animal };
}
```

changeLocation.js

```javascript
export default function changeBreed(location) {
return { type: "CHANGE_BREED", payload: location };
export default function changeBreed(breed) {
return { type: "CHANGE_BREED", payload: breed };
}
```

That's it for action creators. In previous versions of this course, I taught how to do async actions so [check this out if you want to see that][v4-async]. there are a thousand flavors of how to do async with Redux. The most popular are [redux-observable][ro], [redux-saga][rs], [redux-promise][rp], and [redux-thunk][rt]. I showed how to use redux-thunk because it's simplest: the others are more powerful but more complex.

[fsa]: https://github.com/redux-utilities/flux-standard-action
[v4-async]: https://btholt.github.io/complete-intro-to-react-v4/redux
[ro]: https://github.com/redux-observable/redux-observable
[rs]: https://redux-saga.js.org/
[rp]: https://docs.psb.codes/redux-promise-middleware/
Expand Down
2 changes: 1 addition & 1 deletion lessons/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const [theme] = useContext(ThemeContext);
```

- Now your button should be a beautiful shade of `darkblue`.
- `useContext` is how you get the context data out of a given context (you can lots of various types of context in a given app.)
- `useContext` is how you get the context data out of a given context (you can add lots of various types of context in a given app.)
- Right now it's just reading from it and a pretty silly use of context. But let's go make Details.js use it as well.

Let's go do this in Details.js
Expand Down
4 changes: 2 additions & 2 deletions lessons/css-and-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ section: "TailwindCSS"
description: ""
---

There are many ways to do CSS with React. Even just in this course I've done several ways with [style-components][sc] and [emotion][emotion]. Both of those are fantastic pieces of software and could definitely still be used today. As is the case when I teach this course I try to cover the latest material and what I think is the current state-of-the-art of the industry and today I think that is [TailwindCSS][tailwind].
There are many ways to do CSS with React. Even just in this course I've done several ways with [styled-components][sc] and [emotion][emotion]. Both of those are fantastic pieces of software and could definitely still be used today. As is the case when I teach this course I try to cover the latest material and what I think is the current state-of-the-art of the industry and today I think that is [TailwindCSS][tailwind].

Both style-components and emotion are libraries that execute in the JavaScript layer. They bring your CSS into your JavaScript. This allows you all the power of JavaScript to manipulate styles using JavaScript.
Both styled-components and emotion are libraries that execute in the JavaScript layer. They bring your CSS into your JavaScript. This allows you all the power of JavaScript to manipulate styles using JavaScript.

Tailwind however is a different approach to this. And it bears mentioning that Tailwind isn't tied to React at all (whereas styled-components is and emotion mostly is.) Everything I'm showing you here is just incidentally using React (though Tailwind is particularly popular amongst React devs.)

Expand Down
2 changes: 1 addition & 1 deletion lessons/istanbul.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ section: "Testing"
description: ""
---

One last very cool trick that Jest has built into it: [Istanbul][istanbul]. Istanbul (which is not [Constantinople][they-might-be-giants]) is a tool which tells you _how much_ of your code that you're covering with tests. Via an interactive viewer you can see what lines are and aren't covered. This used to be annoying to set up by Jest just does it for you.
One last very cool trick that Jest has built into it: [Istanbul][istanbul]. Istanbul (which is not [Constantinople][they-might-be-giants]) is a tool which tells you _how much_ of your code that you're covering with tests. Via an interactive viewer you can see what lines are and aren't covered. This used to be annoying to set up but Jest just does it for you.

Add the following command to your npm scripts: `"test:coverage": "jest --coverage"` and go ahead run `npm run test:coverage` and open the following file in your browser: `open coverage/lcov-report/index.html`.

Expand Down
6 changes: 3 additions & 3 deletions lessons/portals-and-refs.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ section: "Special Case React Tools"
description: ""
---

Another nice feature React is something called a Portal. You can think of the portal as a separate mount point (the actual DOM node which your app is put into) for your React app. A common use case for this is going to be doing modals. You'll have your normal app with its normal mount point and then you can also put different content into a separate mount point (like a modal or a contextual nav bar) directly from a component. Pretty cool!
Another nice feature in React is something called a Portal. You can think of the portal as a separate mount point (the actual DOM node which your app is put into) for your React app. A common use case for this is going to be doing modals. You'll have your normal app with its normal mount point and then you can also put different content into a separate mount point (like a modal or a contextual nav bar) directly from a component. Pretty cool!

First thing, let's go into index.html and add a separate mount point:

Expand All @@ -15,7 +15,7 @@ First thing, let's go into index.html and add a separate mount point:
<div id="modal"></div>
```

This where the modal will actually be mounted whenever we render to this portal. Totally separate from our app root.
This is where the modal will actually be mounted whenever we render to this portal. Totally separate from our app root.

Next create a file called Modal.js:

Expand Down Expand Up @@ -93,7 +93,7 @@ const {
}
```

- We're using a simple `window.location` redirect since we're heading off site. This is bad accessibility so you should be extra cautious when doing this. The button should be an `<a>` tag but I wanted to show you how to do it. But now if you click Yes on the adopt modal it'll take you to the page when you actually can adopt a pet!
- We're using a simple `window.location` redirect since we're heading off site. This is bad accessibility so you should be extra cautious when doing this. The button should be an `<a>` tag but I wanted to show you how to do it. But now if you click Yes on the adopt modal it'll take you to the page where you actually can adopt a pet!
- Notice that despite we're rendering a whole different part of the DOM we're still referencing the state in Details.js. This is the magic of Portals. You can use state but render in different parts of the DOM. Imagine a sidebar with contextual navigation. Or a contextual footer. It opens up a lot of cool possibilities.

That's it! That's how you make a modal using a portal in React. This used to be significantly more difficult to do but with portals it became trivial. The nice thing about portals is that despite the actual elements being in different DOM trees, these are in the same React trees, so you can do event bubbling up from the modal. Some times this is useful if you want to make your Modal more flexible (like we did.)
Expand Down
2 changes: 1 addition & 1 deletion lessons/react-router.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description: "One component should do one thing. Brian shows you how to break do

React Router is by far the most popular client side router in the React community. It is mature, being used by big companies, and battle tested at large scales. It also has a lot of really cool capabilities, some of which we'll examine here.

What we want to do now is to add a second page to our application: a Details page where you can out more about each animal.
What we want to do now is to add a second page to our application: a Details page where you can find out more about each animal.

Let's quickly make a second page so we can switch between the two. Make file called Details.js.

Expand Down
6 changes: 3 additions & 3 deletions lessons/server-side-rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ section: "Server Side Rendering"

> Please start with a fresh copy of this app: [Adopt Me!][app]

Performance is a central concern for front end developers. We should always be striving to serve the leanest web apps that perform faster than humans can think. This is as much a game of psychology as it is a a technological challenge. It's a challenge of loading the correct content first so a user can see a site and begin to make a decision of what they want to do (scroll down, click a button, log in, etc.) and then be prepared for that action before they make that decision.
Performance is a central concern for front end developers. We should always be striving to serve the leanest web apps that perform faster than humans can think. This is as much a game of psychology as it is a technological challenge. It's a challenge of loading the correct content first so a user can see a site and begin to make a decision of what they want to do (scroll down, click a button, log in, etc.) and then be prepared for that action before they make that decision.

Enter server-side rendering. This is a technique where you run React on your Node.js server _before_ you serve the request to the user and send down the first rendering of your website already done. This saves precious milliseconds+ on your site because otherwise the user has to download the HTML, then download the JavaScript, then execute the JS to get the app. In this case, they'll just download the HTML and see the first rendered page while React is loading in the background.

While the total time to when the page is actually interactive is comparable, if a bit slower, the time to when the user _sees_ something for the first time should be much faster, hence why this is a popular technique. So let's give it a shot.

First, we need to remove all references to `window` or anything browser related from a path that _could_ be called in Node. That means whenever we reference `window`, it'll have to be inside componentDidMount since componentDidMount doesn't get called in Node.

We'll also have change where our app gets rendered. Make a new file called ClientApp.js. Put in there:
We'll also have to change where our app gets rendered. Make a new file called ClientApp.js. Put in there:

```javascript
import { hydrate } from "react-dom";
import { BrowserRouter, BrowserRouter as Router } from "react-router-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";

hydrate(
Expand Down
2 changes: 1 addition & 1 deletion lessons/tailwind-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ section: "TailwindCSS"
description: ""
---

I'm going to need you to suspend everything you know about CSS best practices for this section. At the start this going to feel gross and weird. But stick with me. I initially had similar feelings towards React too.
I'm going to need you to suspend everything you know about CSS best practices for this section. At the start this is going to feel gross and weird. But stick with me. I initially had similar feelings towards React too.

We are not going to be writing _any_ CSS (well, one little bit but THAT'S IT.) Tailwind is all about just using tiny utility classes and then having that be all the CSS you ever need. Let's see something _super basic_.

Expand Down
2 changes: 1 addition & 1 deletion lessons/tailwind-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ variants: {
},
```

This will allow our specific use case. Again, don't dig too much into this because once Parcel 2 lands or you whenever you're using PostCSS 8 this isn't a big deal.
This will allow our specific use case. Again, don't dig too much into this because once Parcel 2 lands or whenever you're using PostCSS 8 this isn't a big deal.

Now add `className="w-60 disabled:opacity-50"` to the breed `<select>`.

Expand Down
10 changes: 5 additions & 5 deletions lessons/ts-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ TypeScript is a thin layer on top of JavaScript that adds the power of a static

This is going to be a brief intro: how to set it up and get going with it. If you want more TypeScript goodness, check out [Mike North's course][mike].

First thing, `npm install -D [email protected]`. Then run `npx tsc --init`. `npx` will run the TypeScript tool directly from your node_modules and init your project for you. You'll see now a tsconfig.json. We don't need to set up anything else since Parcel already knows how to handle TypeScript files. Open your new `tsconfig.json` file and uncomment the `jsx` field. This lets TypeScript that you're writing React. Then update the target to be `ES2020` so that you can use async / await and promises.
First thing, `npm install -D [email protected]`. Then run `npx tsc --init`. `npx` will run the TypeScript tool directly from your node_modules and init your project for you. You'll see now a tsconfig.json. We don't need to set up anything else since Parcel already knows how to handle TypeScript files. Open your new `tsconfig.json` file and uncomment the `jsx` field. This lets TypeScript know that you're writing React. Then update the target to be `ES2020` so that you can use async / await and promises.

Next we need to install the types for our project. Not all projects are written in TypeScript so another project, DefinitelyTyped, provides third party types for your library. In order to install these types, run `npm install -D @types/[email protected] @types/[email protected] @types/[email protected]`. This will grab all these type definitions.
Next we need to install the types for our project. Not all projects are written in TypeScript so another project, [DefinitelyTyped][dt], provides third party types for your library. In order to install these types, run `npm install -D @types/[email protected] @types/[email protected] @types/[email protected]`. This will grab all these type definitions.

This is a migration: we're going to migrate one file at a time to being a TypeScript file. As we migrate each file, we'll change it from being a `.js` file to a `.tsx` file. Let's start with Modal.tsx (make sure you rename it to `.tsx`).

```typescript
import { useEffect, useRef, MutableRefObject, FunctionComponent } from "react";
import { useEffect, useRef, MutableRefObject, ReactNode, FunctionComponent } from "react";
import { createPortal } from "react-dom";

const modalRoot = document.getElementById("modal");

const Modal: FunctionComponent = ({ children }) => {
const Modal: FunctionComponent = ({ children }: { children: ReactNode }) => {
const elRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
if (!elRef.current) {
elRef.current = document.createElement("div");
Expand All @@ -48,7 +48,7 @@ const Modal: FunctionComponent = ({ children }) => {
export default Modal;
```

Fairly similar. We could have made it so the ref could never potentially be null by instantiating it inside the ref. Yes, this will create a new DOM node every time you render, and no that's probably not a big deal for the most part, but it would bother me and so let's do it the same way we did it before. Now we have do null checks anywhere we access `elRef.current`.
Fairly similar. We could have made it so the ref could never potentially be null by instantiating it inside the ref. Yes, this will create a new DOM node every time you render, and no that's probably not a big deal for the most part, but it would bother me and so let's do it the same way we did it before. Now we have to do null checks anywhere we access `elRef.current`.

Then we have to do a null check on modalRoot inside the effect because that could be null too. TypeScript will force you to do this a lot, but it will save you run time errors. Notice we didn't write many types down (just children and the ref type): TypeScript is smart enough to figure out types on its own most of the time.

Expand Down
2 changes: 1 addition & 1 deletion lessons/ts-searchparams.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const json = (await res.json()) as PetAPIResponse;
```

- Occasionally you need to give TypeScript a hint to what it's going to get. That's what `as` for: you're saying I'm sure it's going to be this.
- We have to let React know what sort of parameters this component expects. And in this case it's a React Router route so it expects a path so we need let TypeScript in on the secret. This actually isn't required here but we do know that it will be a route component so might as well be explicit. It makes it easier to come bakc later.
- We have to let React know what sort of parameters this component expects. And in this case it's a React Router route so it expects a path so we need let TypeScript in on the secret. This actually isn't required here but we do know that it will be a route component so might as well be explicit. It makes it easier to come back later.
- We didn't have to add all the Animal typings but since we know it's that we may as well.

> 🏁 [Click here to see the state of the project up until now: typescript-4][step]
Expand Down
2 changes: 1 addition & 1 deletion lessons/usecallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ description: "useCallback is quite similar and indeed it's implemented with the

In this case, we're using a new feature of React called `React.memo`. This is similar to `PureComponent` where a component will do a simple check on its props to see if they've changed and if not it will not re-render this component (or its children, which can bite you.) `React.memo` provides this functionality for function components. Given that, we need to make sure that the function itself given to `ExpensiveComputationComponent` is the _same_ function every time. We can use `useCallback` to make sure that React is handing _the same fibonacci_ to `ExpensiveComputationComponent` every time so it passes its `React.memo` check every single time. Now it's only if `count` changes will it actually re-render (as evidenced by the time.)

Try removing the useCallback call and see if you get the the count to 40+ that the page crawls as it updates every second.
Try removing the useCallback call and see if you get the count to 40+ that the page crawls as it updates every second.

[callback]: https://codesandbox.io/s/github/btholt/react-hooks-examples-v3/tree/master/?module=%2Fsrc%2FCallback.js
2 changes: 1 addition & 1 deletion lessons/usecontext.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: ""

[Component][context]

An early problem with the React problem is called "data tunneling" or "prop drilling". This is when you have a top level component (in our case the parent component) and a child component way down in the hierarchy that need the same data (like the user object.) We could pass that data down, parent-to-child, for each of the intermediary components but that sucks because now each of `LevelTwo`, `LevelThree`, and `LevelFour` all have to know about the user object even when they themselves don't need it, just their children. This is prop drilling: passing down this data in unnecessary intermediaries.
An early problem with the React is called "data tunneling" or "prop drilling". This is when you have a top level component (in our case the parent component) and a child component way down in the hierarchy that need the same data (like the user object.) We could pass that data down, parent-to-child, for each of the intermediary components but that sucks because now each of `LevelTwo`, `LevelThree`, and `LevelFour` all have to know about the user object even when they themselves don't need it, just their children. This is prop drilling: passing down this data in unnecessary intermediaries.

Enter context. Context allows you to create a wormhole where stuff goes in and a wormhole in a child component where that same data comes out and the stuff in the middle doesn't know it's there. Now that data is available anywhere inside of the `UserContext.Provider`. `useContext` just pulls that data out when given a Context object as a parameter. You don't have to use `useState` and `useContext` together (the data can be any shape, not just `useState`-shaped) but I find it convenient when child components need to be able to update the context as well.

Expand Down
Loading