my blog https://overreacted.io

update format

+166 -168
+2 -4
app/[slug]/page.js
··· 18 18 19 19 export default async function PostPage({ params }) { 20 20 const file = await readFile("./public/" + params.slug + "/index.md", "utf8"); 21 - let { content, data } = matter(file); 22 - // TODO: change the source instead of this hack. 23 - content = content.replaceAll("```jsx{", "```jsx {"); 21 + const { content, data } = matter(file); 24 22 const discussUrl = `https://x.com/search?q=${encodeURIComponent( 25 23 `https://overreacted.io/${params.slug}/`, 26 24 )}`; 27 - const editUrl = `https://github.com/gaearon/overreacted.io/edit/master/public/${encodeURIComponent( 25 + const editUrl = `https://github.com/gaearon/overreacted.io/edit/main/public/${encodeURIComponent( 28 26 params.slug, 29 27 )}/index.md`; 30 28 return (
+44 -44
public/a-complete-guide-to-useeffect/index.md
··· 74 74 75 75 Here’s a counter. Look at the highlighted line closely: 76 76 77 - ```jsx{6} 77 + ```jsx {6} 78 78 function Counter() { 79 79 const [count, setCount] = useState(0); 80 80 ··· 102 102 103 103 The first time our component renders, the `count` variable we get from `useState()` is `0`. When we call `setCount(1)`, React calls our component again. This time, `count` will be `1`. And so on: 104 104 105 - ```jsx{3,11,19} 105 + ```jsx {3,11,19} 106 106 // During first render 107 107 function Counter() { 108 108 const count = 0; // Returned by useState() ··· 148 148 149 149 Look at this example. It shows an alert with the `count` after three seconds: 150 150 151 - ```jsx{4-8,16-18} 151 + ```jsx {4-8,16-18} 152 152 function Counter() { 153 153 const [count, setCount] = useState(0); 154 154 ··· 204 204 205 205 This is not specific to React — regular functions work in a similar way: 206 206 207 - ```jsx{2} 207 + ```jsx {2} 208 208 function sayHi(person) { 209 209 const name = person.name; 210 210 setTimeout(() => { ··· 226 226 227 227 This explains how our event handler captures the `count` at the time of the click. If we apply the same substitution principle, each render “sees” its own `count`: 228 228 229 - ```jsx{3,15,27} 229 + ```jsx {3,15,27} 230 230 // During first render 231 231 function Counter() { 232 232 const count = 0; // Returned by useState() ··· 266 266 267 267 So effectively, each render returns its own “version” of `handleAlertClick`. Each of those versions “remembers” its own `count`: 268 268 269 - ```jsx{6,10,19,23,32,36} 269 + ```jsx {6,10,19,23,32,36} 270 270 // During first render 271 271 function Counter() { 272 272 // ... ··· 319 319 320 320 Let’s go back to an example from [the docs](https://reactjs.org/docs/hooks-effect.html): 321 321 322 - ```jsx{4-6} 322 + ```jsx {4-6} 323 323 function Counter() { 324 324 const [count, setCount] = useState(0); 325 325 ··· 350 350 351 351 Each version “sees” the `count` value from the render that it “belongs” to: 352 352 353 - ```jsx{5-8,17-20,29-32} 353 + ```jsx {5-8,17-20,29-32} 354 354 // During first render 355 355 function Counter() { 356 356 // ... ··· 433 433 434 434 Let’s try a thought experiment. Consider this code: 435 435 436 - ```jsx{4-8} 436 + ```jsx {4-8} 437 437 function Counter() { 438 438 const [count, setCount] = useState(0); 439 439 ··· 493 493 494 494 So these two examples are equivalent: 495 495 496 - ```jsx{4} 496 + ```jsx {4} 497 497 function Example(props) { 498 498 useEffect(() => { 499 499 setTimeout(() => { ··· 504 504 } 505 505 ``` 506 506 507 - ```jsx{2,5} 507 + ```jsx {2,5} 508 508 function Example(props) { 509 509 const counter = props.counter; 510 510 useEffect(() => { ··· 524 524 525 525 Here’s a [version of our counter example](https://codesandbox.io/s/rm7z22qnlp) that replicates the class behavior: 526 526 527 - ```jsx{3,6-7,9-10} 527 + ```jsx {3,6-7,9-10} 528 528 function Example() { 529 529 const [count, setCount] = useState(0); 530 530 const latestCount = useRef(count); ··· 588 588 589 589 Now the answer is clear! The effect cleanup doesn’t read the “latest” props, whatever that means. It reads props that belong to the render it’s defined in: 590 590 591 - ```jsx{8-11} 591 + ```jsx {8-11} 592 592 // First render, props are {id: 10} 593 593 function Example() { 594 594 // ... ··· 650 650 651 651 You should think of effects in a similar way. **`useEffect` lets you _synchronize_ things outside of the React tree according to our props and state.** 652 652 653 - ```jsx{2-4} 653 + ```jsx {2-4} 654 654 function Greeting({ name }) { 655 655 useEffect(() => { 656 656 document.title = 'Hello, ' + name; ··· 709 709 710 710 For example, maybe our component re-renders because of a state change: 711 711 712 - ```jsx{11-13} 712 + ```jsx {11-13} 713 713 function Greeting({ name }) { 714 714 const [counter, setCounter] = useState(0); 715 715 ··· 743 743 744 744 This is why if you want to avoid re-running effects unnecessarily, you can provide a dependency array (also known as “deps”) argument to `useEffect`: 745 745 746 - ```jsx{3} 746 + ```jsx {3} 747 747 useEffect(() => { 748 748 document.title = 'Hello, ' + name; 749 749 }, [name]); // Our deps ··· 796 796 797 797 If deps contain every value used by the effect, React knows when to re-run it: 798 798 799 - ```jsx{3} 799 + ```jsx {3} 800 800 useEffect(() => { 801 801 document.title = 'Hello, ' + name; 802 802 }, [name]); ··· 808 808 809 809 But if we specified `[]` for this effect, the new effect function wouldn’t run: 810 810 811 - ```jsx{3} 811 + ```jsx {3} 812 812 useEffect(() => { 813 813 document.title = 'Hello, ' + name; 814 814 }, []); // Wrong: name is missing in deps ··· 822 822 823 823 For example, let’s say we’re writing a counter that increments every second. With a class, our intuition is: “Set up the interval once and destroy it once”. Here’s an [example](https://codesandbox.io/s/n5mjzjy9kl) of how we can do it. When we mentally translate this code to `useEffect`, we instinctively add `[]` to the deps. “I want it to run once”, right? 824 824 825 - ```jsx{9} 825 + ```jsx {9} 826 826 function Counter() { 827 827 const [count, setCount] = useState(0); 828 828 ··· 845 845 846 846 In the first render, `count` is `0`. Therefore, `setCount(count + 1)` in the first render’s effect means `setCount(0 + 1)`. **Since we never re-run the effect because of `[]` deps, it will keep calling `setCount(0 + 1)` every second:** 847 847 848 - ```jsx{8,12,21-22} 848 + ```jsx {8,12,21-22} 849 849 // First render, state is 0 850 850 function Counter() { 851 851 // ... ··· 884 884 885 885 Our effect uses `count` — a value inside the component (but outside the effect): 886 886 887 - ```jsx{1,5} 887 + ```jsx {1,5} 888 888 const count = // ... 889 889 890 890 useEffect(() => { ··· 909 909 910 910 **The first strategy is to fix the dependency array to include _all_ the values inside the component that are used inside the effect.** Let’s include `count` as a dep: 911 911 912 - ```jsx{3,6} 912 + ```jsx {3,6} 913 913 useEffect(() => { 914 914 const id = setInterval(() => { 915 915 setCount(count + 1); ··· 920 920 921 921 This makes the dependency array correct. It may not be *ideal* but that’s the first issue we needed to fix. Now a change to `count` will re-run the effect, with each next interval referencing `count` from its render in `setCount(count + 1)`: 922 922 923 - ```jsx{8,12,24,28} 923 + ```jsx {8,12,24,28} 924 924 // First render, state is 0 925 925 function Counter() { 926 926 // ... ··· 972 972 973 973 We want to get rid of the `count` dependency in our effect. 974 974 975 - ```jsx{3,6} 975 + ```jsx {3,6} 976 976 useEffect(() => { 977 977 const id = setInterval(() => { 978 978 setCount(count + 1); ··· 983 983 984 984 To do this, we need to ask ourselves: **what are we using `count` for?** It seems like we only use it for the `setCount` call. In that case, we don’t actually need `count` in the scope at all. When we want to update state based on the previous state, we can use the [functional updater form](https://reactjs.org/docs/hooks-reference.html#functional-updates) of `setState`: 985 985 986 - ```jsx{3} 986 + ```jsx {3} 987 987 useEffect(() => { 988 988 const id = setInterval(() => { 989 989 setCount(c => c + 1); ··· 1020 1020 1021 1021 Let’s modify the previous example to have two state variables: `count` and `step`. Our interval will increment the count by the value of the `step` input: 1022 1022 1023 - ```jsx{7,10} 1023 + ```jsx {7,10} 1024 1024 function Counter() { 1025 1025 const [count, setCount] = useState(0); 1026 1026 const [step, setStep] = useState(1); ··· 1055 1055 1056 1056 Let’s trade the `step` dependency for a `dispatch` dependency in our effect: 1057 1057 1058 - ```jsx{1,6,9} 1058 + ```jsx {1,6,9} 1059 1059 const [state, dispatch] = useReducer(reducer, initialState); 1060 1060 const { count, step } = state; 1061 1061 ··· 1077 1077 1078 1078 Instead of reading the state *inside* an effect, it dispatches an *action* that encodes the information about *what happened*. This allows our effect to stay decoupled from the `step` state. Our effect doesn’t care *how* we update the state, it just tells us about *what happened*. And the reducer centralizes the update logic: 1079 1079 1080 - ```jsx{8,9} 1080 + ```jsx {8,9} 1081 1081 const initialState = { 1082 1082 count: 0, 1083 1083 step: 1, ··· 1103 1103 1104 1104 In fact, we can! We can put *the reducer itself* inside our component to read props: 1105 1105 1106 - ```jsx{1,6} 1106 + ```jsx {1,6} 1107 1107 function Counter({ step }) { 1108 1108 const [count, dispatch] = useReducer(reducer, 0); 1109 1109 ··· 1138 1138 1139 1139 A common mistake is to think functions shouldn’t be dependencies. For example, this seems like it could work: 1140 1140 1141 - ```jsx{13} 1141 + ```jsx {13} 1142 1142 function SearchResults() { 1143 1143 const [data, setData] = useState({ hits: [] }); 1144 1144 ··· 1186 1186 1187 1187 Now let’s say we later use some state or prop in one of these functions: 1188 1188 1189 - ```jsx{6} 1189 + ```jsx {6} 1190 1190 function SearchResults() { 1191 1191 const [query, setQuery] = useState('react'); 1192 1192 ··· 1213 1213 1214 1214 Luckily, there is an easy solution to this problem. **If you only use some functions *inside* an effect, move them directly *into* that effect:** 1215 1215 1216 - ```jsx{4-12} 1216 + ```jsx {4-12} 1217 1217 function SearchResults() { 1218 1218 // ... 1219 1219 useEffect(() => { ··· 1239 1239 1240 1240 If we later edit `getFetchUrl` to use the `query` state, we’re much more likely to notice that we’re editing it *inside* an effect — and therefore, we need to add `query` to the effect dependencies: 1241 1241 1242 - ```jsx{6,15} 1242 + ```jsx {6,15} 1243 1243 function SearchResults() { 1244 1244 const [query, setQuery] = useState('react'); 1245 1245 ··· 1302 1302 1303 1303 On the other hand, if you’re “honest” about the effect dependencies, you may run into a problem. Since both our effects depend on `getFetchUrl` **(which is different on every render)**, our dependency arrays are useless: 1304 1304 1305 - ```jsx{2-5} 1305 + ```jsx {2-5} 1306 1306 function SearchResults() { 1307 1307 // 🔴 Re-triggers all effects on every render 1308 1308 function getFetchUrl(query) { ··· 1329 1329 1330 1330 **First of all, if a function doesn’t use anything from the component scope, you can hoist it outside the component and then freely use it inside your effects:** 1331 1331 1332 - ```jsx{1-4} 1332 + ```jsx {1-4} 1333 1333 // ✅ Not affected by the data flow 1334 1334 function getFetchUrl(query) { 1335 1335 return 'https://hn.algolia.com/api/v1/search?query=' + query; ··· 1355 1355 Alternatively, you can wrap it into the [`useCallback` Hook](https://reactjs.org/docs/hooks-reference.html#usecallback): 1356 1356 1357 1357 1358 - ```jsx{2-5} 1358 + ```jsx {2-5} 1359 1359 function SearchResults() { 1360 1360 // ✅ Preserves identity when its own deps are the same 1361 1361 const getFetchUrl = useCallback((query) => { ··· 1382 1382 1383 1383 We'll immediately see that it's missing a `query` dependency: 1384 1384 1385 - ```jsx{5} 1385 + ```jsx {5} 1386 1386 function SearchResults() { 1387 1387 const [query, setQuery] = useState('react'); 1388 1388 const getFetchUrl = useCallback(() => { // No query argument ··· 1394 1394 1395 1395 If I fix my `useCallback` deps to include `query`, any effect with `getFetchUrl` in deps will re-run whenever the `query` changes: 1396 1396 1397 - ```jsx{4-7} 1397 + ```jsx {4-7} 1398 1398 function SearchResults() { 1399 1399 const [query, setQuery] = useState('react'); 1400 1400 ··· 1416 1416 1417 1417 This is just a consequence of embracing the data flow and the synchronization mindset. **The same solution works for function props passed from parents:** 1418 1418 1419 - ```jsx{4-8} 1419 + ```jsx {4-8} 1420 1420 function Parent() { 1421 1421 const [query, setQuery] = useState('react'); 1422 1422 ··· 1446 1446 1447 1447 Interestingly, this pattern is broken with classes in a way that really shows the difference between the effect and lifecycle paradigms. Consider this translation: 1448 1448 1449 - ```jsx{5-8,18-20} 1449 + ```jsx {5-8,18-20} 1450 1450 class Parent extends Component { 1451 1451 state = { 1452 1452 query: 'react' ··· 1475 1475 1476 1476 You might be thinking: “Come on Dan, we all know that `useEffect` is like `componentDidMount` and `componentDidUpdate` combined, you can’t keep beating that drum!” **Yet this doesn’t work even with `componentDidUpdate`:** 1477 1477 1478 - ```jsx{8-13} 1478 + ```jsx {8-13} 1479 1479 class Child extends Component { 1480 1480 state = { 1481 1481 data: null ··· 1515 1515 1516 1516 The only real solution to this conundrum with classes is to bite the bullet and pass the `query` itself into the `Child` component. The `Child` doesn’t actually end up *using* the `query`, but it can trigger a refetch when it changes: 1517 1517 1518 - ```jsx{10,22-24} 1518 + ```jsx {10,22-24} 1519 1519 class Parent extends Component { 1520 1520 state = { 1521 1521 query: 'react' ··· 1591 1591 1592 1592 As you probably know, this code is buggy. It doesn’t handle updates. So the second classic example you could find online is something like this: 1593 1593 1594 - ```jsx{8-12} 1594 + ```jsx {8-12} 1595 1595 class Article extends Component { 1596 1596 state = { 1597 1597 article: null ··· 1622 1622 1623 1623 Alternatively, the easiest stopgap approach is to track it with a boolean: 1624 1624 1625 - ```jsx{5,9,16-18} 1625 + ```jsx {5,9,16-18} 1626 1626 function Article({ id }) { 1627 1627 const [article, setArticle] = useState(null); 1628 1628
+11 -11
public/algebraic-effects-for-the-rest-of-us/index.md
··· 35 35 36 36 Let’s recap `try / catch` first. Say you have a function that throws. Maybe there’s a bunch of functions between it and the `catch` block: 37 37 38 - ```jsx{4,19} 38 + ```jsx {4,19} 39 39 function getName(user) { 40 40 let name = user.name; 41 41 if (name === null) { ··· 70 70 71 71 This is an example written in a hypothetical JavaScript dialect (let’s call it ES2025 just for kicks) that lets us *recover* from a missing `user.name`: 72 72 73 - ```jsx{4,19-21} 73 + ```jsx {4,19-21} 74 74 function getName(user) { 75 75 let name = user.name; 76 76 if (name === null) { ··· 103 103 104 104 Instead of throwing an error, we *perform an effect*. Just like we can `throw` any value, we can pass any value to `perform`. In this example, I’m passing a string, but it could be an object, or any other data type: 105 105 106 - ```jsx{4} 106 + ```jsx {4} 107 107 function getName(user) { 108 108 let name = user.name; 109 109 if (name === null) { ··· 115 115 116 116 When we `throw` an error, the engine looks for the closest `try / catch` error handler up the call stack. Similarly, when we `perform` an effect, the engine would search for the closest `try / handle` *effect handler* up the call stack: 117 117 118 - ```jsx{3} 118 + ```jsx {3} 119 119 try { 120 120 makeFriends(arya, gendry); 121 121 } handle (effect) { ··· 127 127 128 128 This effect lets us decide how to handle the case where a name is missing. The novel part here (compared to exceptions) is the hypothetical `resume with`: 129 129 130 - ```jsx{5} 130 + ```jsx {5} 131 131 try { 132 132 makeFriends(arya, gendry); 133 133 } handle (effect) { ··· 139 139 140 140 This is the part you can’t do with `try / catch`. It lets us **jump back to where we performed the effect, and pass something back to it from the handler**. 🤯 141 141 142 - ```jsx{4,6,16,18} 142 + ```jsx {4,6,16,18} 143 143 function getName(user) { 144 144 let name = user.name; 145 145 if (name === null) { ··· 194 194 195 195 For a moment, let’s forget about `async / await` and get back to our example: 196 196 197 - ```jsx{4,19-21} 197 + ```jsx {4,19-21} 198 198 function getName(user) { 199 199 let name = user.name; 200 200 if (name === null) { ··· 223 223 224 224 It turns out, we can call `resume with` asynchronously from our effect handler without making any changes to `getName` or `makeFriends`: 225 225 226 - ```jsx{19-23} 226 + ```jsx {19-23} 227 227 function getName(user) { 228 228 let name = user.name; 229 229 if (name === null) { ··· 264 264 265 265 They let you write code that focuses on *what* you’re doing: 266 266 267 - ```jsx{2,3,5,7,12} 267 + ```jsx {2,3,5,7,12} 268 268 function enumerateFiles(dir) { 269 269 const contents = perform OpenDirectory(dir); 270 270 perform Log('Enumerating files in ', dir); ··· 282 282 283 283 And later wrap it with something that specifies *how*: 284 284 285 - ```jsx{6-7,9-11,13-14} 285 + ```jsx {6-7,9-11,13-14} 286 286 let files = []; 287 287 try { 288 288 enumerateFiles('C:\\'); ··· 323 323 324 324 Effect handlers let us decouple the program logic from its concrete effect implementations without too much ceremony or boilerplate code. For example, we could completely override the behavior in tests to use a fake filesystem and to snapshot logs instead of outputting them to the console: 325 325 326 - ```jsx{19-23} 326 + ```jsx {19-23} 327 327 import { withFakeFileSystem } from 'fake-fs'; 328 328 329 329 function withLogSnapshot(fn) {
+4 -4
public/before-you-memo/index.md
··· 53 53 54 54 If you look at the rendering code closer, you'll notice only a part of the returned tree actually cares about the current `color`: 55 55 56 - ```jsx{2,5-6} 56 + ```jsx {2,5-6} 57 57 export default function App() { 58 58 let [color, setColor] = useState('red'); 59 59 return ( ··· 68 68 69 69 So let's extract that part into a `Form` component and move state _down_ into it: 70 70 71 - ```jsx{4,11,14,15} 71 + ```jsx {4,11,14,15} 72 72 export default function App() { 73 73 return ( 74 74 <> ··· 97 97 98 98 The above solution doesn't work if the piece of state is used somewhere *above* the expensive tree. For example, let's say we put the `color` on the *parent* `<div>`: 99 99 100 - ```jsx{2,4} 100 + ```jsx {2,4} 101 101 export default function App() { 102 102 let [color, setColor] = useState('red'); 103 103 return ( ··· 126 126 127 127 The answer is remarkably plain: 128 128 129 - ```jsx{4,5,10,15} 129 + ```jsx {4,5,10,15} 130 130 export default function App() { 131 131 return ( 132 132 <ColorPicker>
+7 -7
public/how-are-function-components-different-from-classes/index.md
··· 112 112 113 113 Let’s look closely at the `showMessage` method in our class: 114 114 115 - ```jsx{3} 115 + ```jsx {3} 116 116 class ProfilePage extends React.Component { 117 117 showMessage = () => { 118 118 alert('Followed ' + this.props.user); ··· 137 137 138 138 One way to do it would be to read `this.props` early during the event, and then explicitly pass them through into the timeout completion handler: 139 139 140 - ```jsx{2,7} 140 + ```jsx {2,7} 141 141 class ProfilePage extends React.Component { 142 142 showMessage = (user) => { 143 143 alert('Followed ' + user); ··· 162 162 163 163 Perhaps, we could *bind* the methods in the constructor? 164 164 165 - ```jsx{4-5} 165 + ```jsx {4-5} 166 166 class ProfilePage extends React.Component { 167 167 constructor(props) { 168 168 super(props); ··· 190 190 191 191 This means that if you close over props or state from a particular render, you can always count on them staying exactly the same: 192 192 193 - ```jsx{3,4,9} 193 + ```jsx {3,4,9} 194 194 class ProfilePage extends React.Component { 195 195 render() { 196 196 // Capture the props! ··· 246 246 247 247 It’s a bit more obvious if you destructure `props` in the function definition: 248 248 249 - ```jsx{1,3} 249 + ```jsx {1,3} 250 250 function ProfilePage({ user }) { 251 251 const showMessage = () => { 252 252 alert('Followed ' + user); ··· 329 329 330 330 By default, React doesn’t create refs for latest props or state in function components. In many cases you don’t need them, and it would be wasted work to assign them. However, you can track the value manually if you’d like: 331 331 332 - ```jsx{3,6,15} 332 + ```jsx {3,6,15} 333 333 function MessageThread() { 334 334 const [message, setMessage] = useState(''); 335 335 const latestMessage = useRef(''); ··· 354 354 355 355 Generally, you should avoid reading or setting refs *during* rendering because they’re mutable. We want to keep the rendering predictable. **However, if we want to get the latest value of a particular prop or state, it can be annoying to update the ref manually.** We could automate it by using an effect: 356 356 357 - ```jsx{4-8,11} 357 + ```jsx {4-8,11} 358 358 function MessageThread() { 359 359 const [message, setMessage] = useState(''); 360 360
+7 -7
public/how-does-react-tell-a-class-from-a-function/index.md
··· 77 77 78 78 First, we need to understand why it’s important to treat functions and classes differently. Note how we use the `new` operator when calling a class: 79 79 80 - ```jsx{5} 80 + ```jsx {5} 81 81 // If Greeting is a function 82 82 const result = Greeting(props); // <p>Hello</p> 83 83 ··· 116 116 117 117 The `new` operator also makes anything we put on `Person.prototype` available on the `fred` object: 118 118 119 - ```jsx{4-6,9} 119 + ```jsx {4-6,9} 120 120 function Person(name) { 121 121 this.name = name; 122 122 } ··· 244 244 245 245 This behavior is intentional and follows from the design of arrow functions. One of the main perks of arrow functions is that they *don’t* have their own `this` value — instead, `this` is resolved from the closest regular function: 246 246 247 - ```jsx{2,6,7} 247 + ```jsx {2,6,7} 248 248 class Friends extends React.Component { 249 249 render() { 250 250 const friends = this.props.friends; ··· 297 297 298 298 However, JavaScript also allows a function called with `new` to *override* the return value of `new` by returning some other object. Presumably, this was considered useful for patterns like pooling where we want to reuse instances: 299 299 300 - ```jsx{1-2,7-8,17-18} 300 + ```jsx {1-2,7-8,17-18} 301 301 // Created lazily 302 302 var zeroVector = null; 303 303 ··· 371 371 372 372 What’s the `prototype` property on a function or a class, then? **It’s the `__proto__` given to all objects `new`ed with that class or a function!** 373 373 374 - ```jsx{8} 374 + ```jsx {8} 375 375 function Person(name) { 376 376 this.name = name; 377 377 } ··· 409 409 410 410 With classes, you’re not exposed directly to this mechanism, but `extends` also works on top of the good old prototype chain. That’s how our React class instance gets access to methods like `setState`: 411 411 412 - ```jsx{1,9,13} 412 + ```jsx {1,9,13} 413 413 class Greeting extends React.Component { 414 414 render() { 415 415 return <p>Hello</p>; ··· 447 447 448 448 Since the `__proto__` chain mirrors the class hierarchy, we can check whether a `Greeting` extends `React.Component` by starting with `Greeting.prototype`, and then following down its `__proto__` chain: 449 449 450 - ```jsx{3,4} 450 + ```jsx {3,4} 451 451 // `__proto__` chain 452 452 new Greeting() 453 453 → Greeting.prototype // 🕵️ We start here
+3 -3
public/how-does-setstate-know-what-to-do/index.md
··· 7 7 8 8 When you call `setState` in a component, what do you think happens? 9 9 10 - ```jsx{11} 10 + ```jsx {11} 11 11 import React from 'react'; 12 12 import ReactDOM from 'react-dom'; 13 13 ··· 112 112 **The answer is that every renderer sets a special field on the created class.** This field is called `updater`. It’s not something *you* would set — rather, it’s something React DOM, React DOM Server or React Native set right after creating an instance of your class: 113 113 114 114 115 - ```jsx{4,9,14} 115 + ```jsx {4,9,14} 116 116 // Inside React DOM 117 117 const inst = new YourComponent(); 118 118 inst.props = props; ··· 172 172 173 173 And individual renderers set the dispatcher before rendering your component: 174 174 175 - ```jsx{3,8-9} 175 + ```jsx {3,8-9} 176 176 // In React DOM 177 177 const prevDispatcher = React.__currentDispatcher; 178 178 React.__currentDispatcher = ReactDOMDispatcher;
+17 -17
public/making-setinterval-declarative-with-react-hooks/index.md
··· 30 30 31 31 Without further ado, here’s a counter that increments every second: 32 32 33 - ```jsx{6-9} 33 + ```jsx {6-9} 34 34 import React, { useState, useEffect, useRef } from 'react'; 35 35 36 36 function Counter() { ··· 128 128 129 129 So how would you do this with `setInterval` in a class? I ended up with this: 130 130 131 - ```jsx{7-26} 131 + ```jsx {7-26} 132 132 class Counter extends React.Component { 133 133 state = { 134 134 count: 0, ··· 179 179 180 180 <font size="50">🥁🥁🥁</font> 181 181 182 - ```jsx{5-8} 182 + ```jsx {5-8} 183 183 function Counter() { 184 184 let [count, setCount] = useState(0); 185 185 let [delay, setDelay] = useState(1000); ··· 208 208 209 209 Unlike the class version, there is no complexity gap for “upgrading” the `useInterval` Hook example to have a dynamically adjusted delay: 210 210 211 - ```jsx{4,9} 211 + ```jsx {4,9} 212 212 // Constant delay 213 213 useInterval(() => { 214 214 setCount(count + 1); ··· 226 226 227 227 What if I want to temporarily *pause* my interval? I can do this with state too: 228 228 229 - ```jsx{6} 229 + ```jsx {6} 230 230 const [delay, setDelay] = useState(1000); 231 231 const [isRunning, setIsRunning] = useState(true); 232 232 ··· 260 260 261 261 Now I want an interval that increments it every second. It’s a [side effect that needs cleanup](https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup) so I’m going to `useEffect()` and return the cleanup function: 262 262 263 - ```jsx{4-9} 263 + ```jsx {4-9} 264 264 function Counter() { 265 265 let [count, setCount] = useState(0); 266 266 ··· 304 304 305 305 You might know that `useEffect()` lets us [*opt out*](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) of re-applying effects. You can specify a dependency array as a second argument, and React will only re-run the effect if something in that array changes: 306 306 307 - ```jsx{3} 307 + ```jsx {3} 308 308 useEffect(() => { 309 309 document.title = `You clicked ${count} times`; 310 310 }, [count]); ··· 316 316 317 317 In the first attempt, our problem was that re-running the effects caused our timer to get cleared too early. We can try to fix it by never re-running them: 318 318 319 - ```jsx{9} 319 + ```jsx {9} 320 320 function Counter() { 321 321 let [count, setCount] = useState(0); 322 322 ··· 364 364 365 365 Hooks let us apply the same declarative approach to effects: 366 366 367 - ```jsx{4} 367 + ```jsx {4} 368 368 // Describes every interval state 369 369 useInterval(() => { 370 370 setCount(count + 1); ··· 420 420 421 421 `useRef()` returns a plain object with a mutable `current` property that’s shared between renders. We can save the *latest* interval callback into it: 422 422 423 - ```jsx{8} 423 + ```jsx {8} 424 424 function callback() { 425 425 // Can read fresh props, state, etc. 426 426 setCount(count + 1); ··· 434 434 435 435 And then we can read and call it from inside our interval: 436 436 437 - ```jsx{3,8} 437 + ```jsx {3,8} 438 438 useEffect(() => { 439 439 function tick() { 440 440 savedCallback.current(); ··· 449 449 450 450 Here’s a complete working solution: 451 451 452 - ```jsx{10,15} 452 + ```jsx {10,15} 453 453 function Counter() { 454 454 const [count, setCount] = useState(0); 455 455 const savedCallback = useRef(); ··· 487 487 488 488 Ideally, I just want to write this: 489 489 490 - ```jsx{4-6} 490 + ```jsx {4-6} 491 491 function Counter() { 492 492 const [count, setCount] = useState(0); 493 493 ··· 534 534 535 535 Now that the `delay` can change between renders, I need to declare it in the dependencies of my interval effect: 536 536 537 - ```jsx{8} 537 + ```jsx {8} 538 538 useEffect(() => { 539 539 function tick() { 540 540 savedCallback.current(); ··· 586 586 587 587 Say we want to be able to pause our interval by passing `null` as the `delay`: 588 588 589 - ```jsx{6} 589 + ```jsx {6} 590 590 const [delay, setDelay] = useState(1000); 591 591 const [isRunning, setIsRunning] = useState(true); 592 592 ··· 597 597 598 598 How do we implement this? The answer is: by not setting up an interval. 599 599 600 - ```jsx{6} 600 + ```jsx {6} 601 601 useEffect(() => { 602 602 function tick() { 603 603 savedCallback.current(); ··· 622 622 623 623 ![Counter that automatically speeds up](./counter_inception.gif) 624 624 625 - ```jsx{10-15} 625 + ```jsx {10-15} 626 626 function Counter() { 627 627 const [delay, setDelay] = useState(1000); 628 628 const [count, setCount] = useState(0);
+1 -1
public/my-wishlist-for-hot-reloading/index.md
··· 59 59 60 60 For a long time, it seemed to me that implementing reliable hot reloading for functions *alone* would encourage people to write convoluted code just to avoid using classes. But with [Hooks](https://reactjs.org/docs/hooks-intro.html), function components are fully featured so this is not a concern anymore. And this approach “just works” with Hooks: 61 61 62 - ```jsx{4} 62 + ```jsx {4} 63 63 // Reassigns the latest version 64 64 window.latest_Button = function(props) { 65 65 // Your actual code is moved here by a plugin
+23 -23
public/react-as-a-ui-runtime/index.md
··· 134 134 135 135 React will look at the `reactElement.type` (in our example, `'button'`) and ask the React DOM renderer to create a host instance for it and set the properties: 136 136 137 - ```jsx{3,4} 137 + ```jsx {3,4} 138 138 // Somewhere in the ReactDOM renderer (simplified) 139 139 function createHostInstance(reactElement) { 140 140 let domNode = document.createElement(reactElement.type); ··· 145 145 146 146 In our example, effectively React will do this: 147 147 148 - ```jsx{1,2} 148 + ```jsx {1,2} 149 149 let domNode = document.createElement('button'); 150 150 domNode.className = 'blue'; 151 151 ··· 158 158 159 159 What happens if we call `ReactDOM.render()` twice with the same container? 160 160 161 - ```jsx{2,11} 161 + ```jsx {2,11} 162 162 ReactDOM.render( 163 163 <button className="blue" />, 164 164 document.getElementById('container') ··· 208 208 209 209 Here is an example with comments showing roughly what React does: 210 210 211 - ```jsx{9,10,16,26,27} 211 + ```jsx {9,10,16,26,27} 212 212 // let domNode = document.createElement('button'); 213 213 // domNode.className = 'blue'; 214 214 // domContainer.appendChild(domNode); ··· 250 250 251 251 Say we want to first show only an input, but later render a message before it: 252 252 253 - ```jsx{12} 253 + ```jsx {12} 254 254 // First render 255 255 ReactDOM.render( 256 256 <dialog> ··· 277 277 278 278 So effectively the update code executed by React would be like: 279 279 280 - ```jsx{1,2,8,9} 280 + ```jsx {1,2,8,9} 281 281 let oldInputNode = dialogNode.firstChild; 282 282 dialogNode.removeChild(oldInputNode); 283 283 ··· 312 312 313 313 This example doesn’t suffer from the problem we just described. It might be easier to see why if we use object notation instead of JSX. Look at the `dialog` child element tree: 314 314 315 - ```jsx{12-15} 315 + ```jsx {12-15} 316 316 function Form({ showMessage }) { 317 317 let message = null; 318 318 if (showMessage) { ··· 392 392 393 393 **This is why React nags you to specify a special property called `key` every time you include an array of elements in your output:** 394 394 395 - ```jsx{5} 395 + ```jsx {5} 396 396 function ShoppingList({ list }) { 397 397 return ( 398 398 <form> ··· 454 454 455 455 However, *local mutation* is absolutely fine: 456 456 457 - ```jsx{2,5} 457 + ```jsx {2,5} 458 458 function FriendList({ friends }) { 459 459 let items = []; 460 460 for (let i = 0; i < friends.length; i++) { ··· 602 602 603 603 Consider this component putting `<Comments>` inside a `<Page>`: 604 604 605 - ```jsx{11} 605 + ```jsx {11} 606 606 function Story({ currentUser }) { 607 607 // return { 608 608 // type: Page, ··· 621 621 622 622 The `Page` component can render the children given to it inside some `Layout`: 623 623 624 - ```jsx{4} 624 + ```jsx {4} 625 625 function Page({ user, children }) { 626 626 return ( 627 627 <Layout> ··· 635 635 636 636 But what if it has an early exit condition? 637 637 638 - ```jsx{2-4} 638 + ```jsx {2-4} 639 639 function Page({ user, children }) { 640 640 if (!user.isLoggedIn) { 641 641 return <h1>Please log in</h1>; ··· 650 650 651 651 If we called `Comments()` as a function, it would execute immediately regardless of whether `Page` wants to render them or not: 652 652 653 - ```jsx{4,8} 653 + ```jsx {4,8} 654 654 // { 655 655 // type: Page, 656 656 // props: { ··· 664 664 665 665 But if we pass a React element, we don’t execute `Comments` ourselves at all: 666 666 667 - ```jsx{4,8} 667 + ```jsx {4,8} 668 668 // { 669 669 // type: Page, 670 670 // props: { ··· 689 689 690 690 We call these features *Hooks*. For example, `useState` is a Hook. 691 691 692 - ```jsx{2,6,7} 692 + ```jsx {2,6,7} 693 693 function Example() { 694 694 const [count, setCount] = useState(0); 695 695 ··· 723 723 724 724 When trees get too deep or wide, you can tell React to [memoize](https://en.wikipedia.org/wiki/Memoization) a subtree and reuse previous render results during shallow equal prop changes: 725 725 726 - ```jsx{5} 726 + ```jsx {5} 727 727 function Row({ item }) { 728 728 // ... 729 729 } ··· 754 754 755 755 Several components may want to update state in response to the same event. This example is contrived but it illustrates a common pattern: 756 756 757 - ```jsx{4,14} 757 + ```jsx {4,14} 758 758 function Parent() { 759 759 let [count, setCount] = useState(0); 760 760 return ( ··· 779 779 780 780 If React immediately re-rendered components in response to `setState` calls, we’d end up rendering the child twice: 781 781 782 - ```jsx{4,8} 782 + ```jsx {4,8} 783 783 *** Entering React's browser click event handler *** 784 784 Child (onClick) 785 785 - setState ··· 916 916 917 917 In React, this is done by declaring an effect: 918 918 919 - ```jsx{4-6} 919 + ```jsx {4-6} 920 920 function Example() { 921 921 const [count, setCount] = useState(0); 922 922 ··· 952 952 953 953 Sometimes, re-running the effect on every render can be undesirable. You can tell React to [skip](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) applying an effect if certain variables didn’t change: 954 954 955 - ```jsx{3} 955 + ```jsx {3} 956 956 useEffect(() => { 957 957 document.title = `You clicked ${count} times`; 958 958 }, [count]); ··· 981 981 982 982 To solve this, make sure that if you specify the dependency array, it includes **all** things that can change, including the functions: 983 983 984 - ```jsx{4} 984 + ```jsx {4} 985 985 useEffect(() => { 986 986 DataSource.addSubscription(handleChange); 987 987 return () => DataSource.removeSubscription(handleChange); ··· 996 996 997 997 Since Hooks like `useState` and `useEffect` are function calls, we can compose them into our own Hooks: 998 998 999 - ```jsx{2,8} 999 + ```jsx {2,8} 1000 1000 function MyResponsiveComponent() { 1001 1001 const width = useWindowWidth(); // Our custom Hook 1002 1002 return ( ··· 1027 1027 1028 1028 If `use` *were* a syntax, it would make sense for it to be at the top level: 1029 1029 1030 - ```jsx{3} 1030 + ```jsx {3} 1031 1031 // 😉 Note: not a real syntax 1032 1032 component Example(props) { 1033 1033 const [count, setCount] = use State(0);
+1 -1
public/the-bug-o-notation/index.md
··· 116 116 117 117 This code might not look too different. It’s even a bit more verbose. But it is *dramatically* simpler to debug because of this line: 118 118 119 - ```jsx{3} 119 + ```jsx {3} 120 120 function setState(nextState) { 121 121 // Clear all existing children 122 122 formStatus.innerHTML = '';
+12 -12
public/why-do-hooks-rely-on-call-order/index.md
··· 35 35 36 36 There is one specific part that I’d like to focus on today. As you may recall, each Hook can be used in a component more than once. For example, we can declare [multiple state variables](https://reactjs.org/docs/hooks-state.html#tip-using-multiple-state-variables) by calling `useState()` repeatedly: 37 37 38 - ```jsx{2,3,4} 38 + ```jsx {2,3,4} 39 39 function Form() { 40 40 const [name, setName] = useState('Mary'); // State variable 1 41 41 const [surname, setSurname] = useState('Poppins'); // State variable 2 ··· 103 103 104 104 But the point of supporting multiple `useState()` calls is so that you can *extract* parts of stateful logic (state + effects) out of your components into custom Hooks which can *also* independently use local state and effects: 105 105 106 - ```jsx{6-7} 106 + ```jsx {6-7} 107 107 function Form() { 108 108 // Declare some state variables directly in component body 109 109 const [name, setName] = useState('Mary'); ··· 174 174 175 175 This proposal seems to work for extracting the `useWindowWidth()` Hook: 176 176 177 - ```jsx{4,11-17} 177 + ```jsx {4,11-17} 178 178 // ⚠️ This is NOT the React Hooks API 179 179 function Form() { 180 180 // ... ··· 196 196 197 197 But if we attempt to extract input handling, it would fail: 198 198 199 - ```jsx{4,5,19-29} 199 + ```jsx {4,5,19-29} 200 200 // ⚠️ This is NOT the React Hooks API 201 201 function Form() { 202 202 // ... ··· 251 251 252 252 Two custom Hooks like `useWindowWidth()` and `useNetworkStatus()` might want to use the same custom Hook like `useSubscription()` under the hood: 253 253 254 - ```jsx{12,23-27,32-42} 254 + ```jsx {12,23-27,32-42} 255 255 function StatusMessage() { 256 256 const width = useWindowWidth(); 257 257 const isOnline = useNetworkStatus(); ··· 330 330 331 331 One way could be to isolate state keys with closures. This would require you to “instantiate” custom Hooks and add a function wrapper around each of them: 332 332 333 - ```jsx{5,6} 333 + ```jsx {5,6} 334 334 /******************* 335 335 * useFormInput.js * 336 336 ******************/ ··· 354 354 355 355 Additionally, you have to repeat every custom Hook used in a component twice. Once in the top level scope (or inside a function scope if we’re writing a custom Hook), and once at the actual call site. This means you have to jump between the rendering and top-level declarations even for small changes: 356 356 357 - ```jsx{2,3,7,8} 357 + ```jsx {2,3,7,8} 358 358 // ⚠️ This is NOT the React Hooks API 359 359 const useNameFormInput = createUseFormInput(); 360 360 const useSurnameFormInput = createUseFormInput(); ··· 386 386 387 387 The idea is that we could *compose* keys every time we write a custom Hook. Something like this: 388 388 389 - ```jsx{4,5,16,17} 389 + ```jsx {4,5,16,17} 390 390 // ⚠️ This is NOT the React Hooks API 391 391 function Form() { 392 392 // ... ··· 423 423 424 424 What does this code mean exactly? 425 425 426 - ```jsx{3,4} 426 + ```jsx {3,4} 427 427 // ⚠️ This is NOT the React Hooks API 428 428 function Counter(props) { 429 429 if (props.isActive) { ··· 442 442 443 443 If conditional state gets preserved, what about an effect? 444 444 445 - ```jsx{5-8} 445 + ```jsx {5-8} 446 446 // ⚠️ This is NOT the React Hooks API 447 447 function Counter(props) { 448 448 if (props.isActive) { ··· 487 487 488 488 Here is a hypothetical example of a message recipient picker that shows whether the currently chosen friend is online: 489 489 490 - ```jsx{8,9} 490 + ```jsx {8,9} 491 491 const friendList = [ 492 492 { id: 1, name: 'Phoebe' }, 493 493 { id: 2, name: 'Rachel' }, ··· 532 532 533 533 This works because we can pass the return value of the `useState()` Hook to the `useFriendStatus()` Hook: 534 534 535 - ```jsx{2} 535 + ```jsx {2} 536 536 const [recipientID, setRecipientID] = useState(1); 537 537 const isRecipientOnline = useFriendStatus(recipientID); 538 538 ```
+3 -3
public/why-do-react-elements-have-typeof-property/index.md
··· 23 23 24 24 And that function gives you back an object. We call this object a React *element*. It tells React what to render next. Your components return a tree of them. 25 25 26 - ```jsx{9} 26 + ```jsx {9} 27 27 { 28 28 type: 'marquee', 29 29 props: { ··· 105 105 106 106 However, **if your server has a hole that lets the user store an arbitrary JSON object** while the client code expects a string, this could become a problem: 107 107 108 - ```jsx{2-10,15} 108 + ```jsx {2-10,15} 109 109 // Server could have a hole that lets user store JSON 110 110 let expectedTextButGotJSON = { 111 111 type: 'div', ··· 128 128 129 129 The fix in React 0.14 was to [tag every React element with a Symbol](https://github.com/facebook/react/pull/4832): 130 130 131 - ```jsx{9} 131 + ```jsx {9} 132 132 { 133 133 type: 'marquee', 134 134 props: {
+3 -3
public/why-do-we-write-super-props/index.md
··· 15 15 16 16 I wrote `super(props)` more times in my life than I’d like to know: 17 17 18 - ```jsx{3} 18 + ```jsx {3} 19 19 class Checkbox extends React.Component { 20 20 constructor(props) { 21 21 super(props); ··· 38 38 39 39 But let’s get back to this example using only ES2015 features: 40 40 41 - ```jsx{3} 41 + ```jsx {3} 42 42 class Checkbox extends React.Component { 43 43 constructor(props) { 44 44 super(props); ··· 145 145 146 146 **Probably not because it’s still confusing.** Sure, React would later assign `this.props` *after* your constructor has run. But `this.props` would still be undefined *between* the `super` call and the end of your constructor: 147 147 148 - ```jsx{14} 148 + ```jsx {14} 149 149 // Inside React 150 150 class Component { 151 151 constructor(props) {
+4 -4
public/why-isnt-x-a-hook/index.md
··· 61 61 62 62 Hooks are useful because you can pass values *between* Hooks: 63 63 64 - ```jsx{4,12,14} 64 + ```jsx {4,12,14} 65 65 function useWindowWidth() { 66 66 const [width, setWidth] = useState(window.innerWidth); 67 67 // ... ··· 108 108 109 109 `React.memo()` takes a component and returns a component: 110 110 111 - ```jsx{4} 111 + ```jsx {4} 112 112 function Button(props) { 113 113 // ... 114 114 } ··· 138 138 139 139 Let’s say we try to put `useBailout()` in two custom Hooks: 140 140 141 - ```jsx{4,5,19,20} 141 + ```jsx {4,5,19,20} 142 142 function useFriendStatus(friendID) { 143 143 const [isOnline, setIsOnline] = useState(null); 144 144 ··· 173 173 Now what happens if you use them both in the same component? 174 174 175 175 176 - ```jsx{2,3} 176 + ```jsx {2,3} 177 177 function ChatThread({ friendID, isTyping }) { 178 178 const width = useWindowWidth(); 179 179 const isOnline = useFriendStatus(friendID);
+24 -24
public/writing-resilient-components/index.md
··· 91 91 92 92 However, a common mistake when learning React is to copy props into state: 93 93 94 - ```jsx{3,6} 94 + ```jsx {3,6} 95 95 class Button extends React.Component { 96 96 state = { 97 97 color: this.props.color ··· 133 133 134 134 Computed values are another reason people sometimes attempt to copy props into state. For example, imagine that we determined the *button text* color based on an expensive computation with background `color` as an argument: 135 135 136 - ```jsx{3,9} 136 + ```jsx {3,9} 137 137 class Button extends React.Component { 138 138 state = { 139 139 textColor: slowlyCalculateTextColor(this.props.color) ··· 153 153 154 154 This component is buggy because it doesn’t recalculate `this.state.textColor` on the `color` prop change. The easiest fix would be to move the `textColor` calculation into the `render` method, and make this a `PureComponent`: 155 155 156 - ```jsx{1,3} 156 + ```jsx {1,3} 157 157 class Button extends React.PureComponent { 158 158 render() { 159 159 const textColor = slowlyCalculateTextColor(this.props.color); ··· 173 173 174 174 However, we might want to optimize it further. What if it’s the `children` prop that changed? It seems unfortunate to recalculate the `textColor` in that case. Our second attempt might be to invoke the calculation in `componentDidUpdate`: 175 175 176 - ```jsx{5-12} 176 + ```jsx {5-12} 177 177 class Button extends React.Component { 178 178 state = { 179 179 textColor: slowlyCalculateTextColor(this.props.color) ··· 207 207 208 208 With a class, you could use a [helper](https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization) for memoization. However, Hooks take this a step further, giving you a built-in way to memoize expensive computations: 209 209 210 - ```jsx{2-5} 210 + ```jsx {2-5} 211 211 function Button({ color, children }) { 212 212 const textColor = useMemo( 213 213 () => slowlyCalculateTextColor(color), ··· 235 235 236 236 Consider this React component: 237 237 238 - ```jsx{5-7} 238 + ```jsx {5-7} 239 239 class SearchResults extends React.Component { 240 240 state = { 241 241 data: null ··· 258 258 259 259 A lot of React components are like this — but if we look a bit closer, we'll notice a bug. The `fetchResults` method uses the `query` prop for data fetching: 260 260 261 - ```jsx{2} 261 + ```jsx {2} 262 262 getFetchUrl() { 263 263 return 'http://myapi/results?query' + this.props.query; 264 264 } ··· 275 275 * Make sure that whenever those props change, we re-run the side effect. 276 276 - We can do this by adding the `componentDidUpdate` method. 277 277 278 - ```jsx{8-12,18} 278 + ```jsx {8-12,18} 279 279 class SearchResults extends React.Component { 280 280 state = { 281 281 data: null ··· 305 305 306 306 However, it’s challenging to remember not to break it again. For example, we might add `currentPage` to the local state, and use it in `getFetchUrl`: 307 307 308 - ```jsx{4,21} 308 + ```jsx {4,21} 309 309 class SearchResults extends React.Component { 310 310 state = { 311 311 data: null, ··· 350 350 351 351 Let’s fix our component to handle updates to the `currentPage` state: 352 352 353 - ```jsx{11,24} 353 + ```jsx {11,24} 354 354 class SearchResults extends React.Component { 355 355 state = { 356 356 data: null, ··· 391 391 392 392 However, one *could* design an API that *can* be statically analyzed for consistency. The [React `useEffect` Hook](/a-complete-guide-to-useeffect/) is an example of such API: 393 393 394 - ```jsx{13-14,19} 394 + ```jsx {13-14,19} 395 395 function SearchResults({ query }) { 396 396 const [data, setData] = useState(null); 397 397 const [currentPage, setCurrentPage] = useState(0); ··· 442 442 443 443 **However, if you try to “optimize” a component by writing your own comparison, you may mistakenly forget to compare function props:** 444 444 445 - ```jsx{2-5,7} 445 + ```jsx {2-5,7} 446 446 class Button extends React.Component { 447 447 shouldComponentUpdate(prevProps) { 448 448 // 🔴 Doesn't compare this.props.onClick ··· 464 464 465 465 It is easy to miss this mistake at first because with classes, you’d usually pass a *method* down, and so it would have the same identity anyway: 466 466 467 - ```jsx{2-4,9-11} 467 + ```jsx {2-4,9-11} 468 468 class MyForm extends React.Component { 469 469 handleClick = () => { // ✅ Always the same function 470 470 // Do something ··· 484 484 485 485 So our optimization doesn’t break *immediately*. However, it will keep “seeing” the old `onClick` value if it changes over time but other props don’t: 486 486 487 - ```jsx{6,13-15} 487 + ```jsx {6,13-15} 488 488 class MyForm extends React.Component { 489 489 state = { 490 490 isEnabled: true ··· 513 513 514 514 This could get even more confusing if the function identity itself depends on something that could change over time, like `draft.content` in this example: 515 515 516 - ```jsx{6-7} 516 + ```jsx {6-7} 517 517 drafts.map(draft => 518 518 <Button 519 519 color='blue' ··· 533 533 534 534 I recommend to avoid manually implementing `shouldComponentUpdate` and to avoid specifying a custom comparison to `React.memo()`. The default shallow comparison in `React.memo` will respect changing function identity: 535 535 536 - ```jsx{11} 536 + ```jsx {11} 537 537 function Button({ onClick, color, children }) { 538 538 const textColor = slowlyCalculateTextColor(color); 539 539 return ( ··· 553 553 554 554 If you insist on a custom comparison, **make sure that you don’t skip functions:** 555 555 556 - ```jsx{5} 556 + ```jsx {5} 557 557 shouldComponentUpdate(prevProps) { 558 558 // ✅ Compares this.props.onClick 559 559 return ( ··· 586 586 587 587 How can one violate this principle? React doesn’t make it very easy — but you can do it by using the legacy `componentWillReceiveProps` lifecycle method: 588 588 589 - ```jsx{5-8} 589 + ```jsx {5-8} 590 590 class TextInput extends React.Component { 591 591 state = { 592 592 value: '' ··· 659 659 660 660 To stress-test your component, you can temporarily add this code to its parent: 661 661 662 - ```jsx{2} 662 + ```jsx {2} 663 663 componentDidMount() { 664 664 // Don't forget to remove this immediately! 665 665 setInterval(() => this.forceUpdate(), 100); ··· 674 674 675 675 This code should work, right? 676 676 677 - ```jsx{1-2} 677 + ```jsx {1-2} 678 678 // 🤔 Should prevent unnecessary re-renders... right? 679 679 class TextInput extends React.PureComponent { 680 680 state = { ··· 702 702 703 703 However, this gives us a false sense of security. **This component is still not resilient to _actual_ prop changes.** For example, if we added *another* often-changing prop, like an animated `style`, we would still “lose” the internal state: 704 704 705 - ```jsx{2} 705 + ```jsx {2} 706 706 <TextInput 707 707 style={{opacity: someValueFromState}} 708 708 value={ ··· 727 727 728 728 It’s easy to check for these problems. Just for fun, try to render your app twice: 729 729 730 - ```jsx{3,4} 730 + ```jsx {3,4} 731 731 ReactDOM.render( 732 732 <> 733 733 <MyApp /> ··· 743 743 744 744 An example of a problematic pattern I’ve written myself a few times is performing global state “cleanup” in `componentWillUnmount`: 745 745 746 - ```jsx{2-3} 746 + ```jsx {2-3} 747 747 componentWillUnmount() { 748 748 // Resets something in Redux store 749 749 this.props.resetForm(); ··· 752 752 753 753 Of course, if there are two such components on the page, unmounting one of them can break the other one. Resetting “global” state on *mount* is no better: 754 754 755 - ```jsx{2-3} 755 + ```jsx {2-3} 756 756 componentDidMount() { 757 757 // Resets something in Redux store 758 758 this.props.resetForm();