generated from btholt/next-course-starter
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
140 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
description: "An essential tool in any React developer's toolbox is the official React Dev Tools extension. Brian shows you how to install and use them." | ||
--- | ||
|
||
React has some really great tools to enhance your developer experience. We'll go over a few of them here. | ||
|
||
## `NODE_ENV=development` | ||
|
||
React already has a lot of developer conveniences built into it out of the box. What's better is that they automatically strip it out when you compile your code for production. | ||
|
||
So how do you get the debugging conveniences then? Well, if you're using Vite.js, it will compile your development server with an environment variable of `NODE_ENV=development` and then when you run `vite build` it will automatically change that to `NODE_ENV=production` which is how all the extra weight gets stripped out. | ||
|
||
Why is it important that we strip the debug stuff out? The dev bundle of React is quite a bit bigger and quite a bit slower than the production build. Make sure you're compiling with the correct environmental variables or your users will suffer. | ||
|
||
## Strict Mode | ||
|
||
React has a new strict mode. If you wrap your app in `<StrictMode></StrictMode>` it will give you additional warnings about things you shouldn't be doing. I'm not teaching you anything that would trip warnings from `StrictMode` but it's good to keep your team in line and not using legacy features or things that will be soon be deprecated. | ||
|
||
Be aware that `StrictMode` continually double-renders your components and will run effects twice. It does this catch subtle bugs where your app will change between renders when it's not meant to. It can be helpful, but to be honest, once you learn to write React the correct way you'll nearly never hit that sort of bug. | ||
|
||
## Dev Tools | ||
|
||
React has wonderful dev tools that the core team maintains. They're available for both Chromium-based browsers and Firefox. They let you do several things like explore your React app like a DOM tree, modify state and props on the fly to test things out, tease out performance problems, and programtically manipulate components. Definitely worth downloading now. [See here][dev-tools] for links. | ||
|
||
[dev-tools]: https://react.dev/learn/react-developer-tools |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
One thing that's pretty special about hooks is their composability. You can use hooks to make other hooks! People tend to call these custom hooks. There are even people who go as far to say "never make an API request in a component, always do it in a hook." I don't know if I'm as hardcore as that but I see the logic in it. If you make a custom hook for those sorts of things they become individually testable and do a good job to separate your display of data and your logic to acquire data. I'm more in the camp of make custom hooks for either complicated logic or reusable logic, but for simple cases it's okay to keep things simple. | ||
|
||
Okay, so we want to add a "Pizza of the Day" banner at the bottom of our page. This necessitates calling a special API to get the pizza of the day (which should change every day based on your computer's time.) Let's first write the component that's going to use it. | ||
|
||
Make a file called PizzaOftheDay.jsx | ||
|
||
```javascript | ||
import { usePizzaOfTheDay } from "./usePizzaOfTheDay"; | ||
|
||
// feel free to change en-US / USD to your locale | ||
const intl = new Intl.NumberFormat("en-US", { | ||
style: "currency", | ||
currency: "USD", | ||
}); | ||
|
||
const PizzaOfTheDay = () => { | ||
const pizzaOfTheDay = usePizzaOfTheDay(); | ||
|
||
if (!pizzaOfTheDay) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
return ( | ||
<div> | ||
<div className="pizza-of-the-day-info"> | ||
<h2>Pizza of the Day</h2> | ||
<h3>{pizzaOfTheDay.name}</h3> | ||
<p>{pizzaOfTheDay.description}</p> | ||
</div> | ||
<img | ||
className="pizza-of-the-day-image" | ||
src={pizzaOfTheDay.image} | ||
alt={pizzaOfTheDay.name} | ||
/> | ||
<p className="pizza-of-the-day-price"> | ||
From: <span>{intl.format(pizzaOfTheDay.sizes.S)}</span> | ||
</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export default PizzaOfTheDay; | ||
``` | ||
|
||
- The cool part here is the `usePizzaOfTheDay()`. We now just get to rely on that this going to provide us with the pizza of the day from within the black box of the hook working. | ||
|
||
Okay, let's go make the hook! Make a file called usePizzaOfTheDay.jsx (you could call this .js instead of jsx but in a React project I just use JSX for all "React-y" things) | ||
|
||
```javascript | ||
import { useState, useEffect } from "react"; | ||
|
||
export const usePizzaOfTheDay = () => { | ||
const [pizzaOfTheDay, setPizzaOfTheDay] = useState(null); | ||
|
||
useEffect(() => { | ||
async function fetchPizzaOfTheDay() { | ||
const response = await fetch("/api/pizza-of-the-day"); | ||
const data = await response.json(); | ||
setPizzaOfTheDay(data); | ||
} | ||
|
||
fetchPizzaOfTheDay(); | ||
}, []); | ||
|
||
return pizzaOfTheDay; | ||
}; | ||
``` | ||
|
||
- This looks like what you'd see at the top of a component, right? Now it's just encapsulated as a hook which makes it easy to test by itself! 🎉 | ||
- We can use `useState`, `useEffect`, or any hook we want here! We can even use other custom hooks! | ||
|
||
Lastly, let's go add this to App.jsx so our component renders. | ||
|
||
```javascript | ||
// import at top | ||
import PizzaOfTheDay from "./PizzaOfTheDay"; | ||
|
||
// under <Order /> | ||
<PizzaOfTheDay />; | ||
``` | ||
|
||
You should now see the new component which uses our new hook at the bottom! | ||
|
||
Let's add one more fun debugging technique made especially for custom hooks. Put this in usePizzaOfTheDay.jsx: | ||
|
||
```javascript | ||
// import useDebugValue | ||
import { useState, useEffect, useDebugValue } from "react"; | ||
|
||
// add under the hook being used in the render function | ||
useDebugValue(pizzaOfTheDay ? `${pizzaOfTheDay.name}` : "Loading..."); | ||
``` | ||
|
||
Now open your React Dev Tools and inspect our PizzaOfTheDay component. You'll see our debug value there. This is helpful when you have _lots_ of custom hooks and in particular lots of reused custom hooks that have differing values. It can help at a glance to discern which hook has which data inside of it. | ||
|
||
> 🏁 [Click here to see the state of the project up until now: 05-custom-hooks][step] | ||
[step]: https://github.com/btholt/citr-v9-project/tree/master/05-custom-hooks |