···74747575Here’s a counter. Look at the highlighted line closely:
76767777-```jsx{6}
7777+```jsx {6}
7878function Counter() {
7979 const [count, setCount] = useState(0);
8080···102102103103The 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:
104104105105-```jsx{3,11,19}
105105+```jsx {3,11,19}
106106// During first render
107107function Counter() {
108108 const count = 0; // Returned by useState()
···148148149149Look at this example. It shows an alert with the `count` after three seconds:
150150151151-```jsx{4-8,16-18}
151151+```jsx {4-8,16-18}
152152function Counter() {
153153 const [count, setCount] = useState(0);
154154···204204205205This is not specific to React — regular functions work in a similar way:
206206207207-```jsx{2}
207207+```jsx {2}
208208function sayHi(person) {
209209 const name = person.name;
210210 setTimeout(() => {
···226226227227This 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`:
228228229229-```jsx{3,15,27}
229229+```jsx {3,15,27}
230230// During first render
231231function Counter() {
232232 const count = 0; // Returned by useState()
···266266267267So effectively, each render returns its own “version” of `handleAlertClick`. Each of those versions “remembers” its own `count`:
268268269269-```jsx{6,10,19,23,32,36}
269269+```jsx {6,10,19,23,32,36}
270270// During first render
271271function Counter() {
272272 // ...
···319319320320Let’s go back to an example from [the docs](https://reactjs.org/docs/hooks-effect.html):
321321322322-```jsx{4-6}
322322+```jsx {4-6}
323323function Counter() {
324324 const [count, setCount] = useState(0);
325325···350350351351Each version “sees” the `count` value from the render that it “belongs” to:
352352353353-```jsx{5-8,17-20,29-32}
353353+```jsx {5-8,17-20,29-32}
354354// During first render
355355function Counter() {
356356 // ...
···433433434434Let’s try a thought experiment. Consider this code:
435435436436-```jsx{4-8}
436436+```jsx {4-8}
437437function Counter() {
438438 const [count, setCount] = useState(0);
439439···493493494494So these two examples are equivalent:
495495496496-```jsx{4}
496496+```jsx {4}
497497function Example(props) {
498498 useEffect(() => {
499499 setTimeout(() => {
···504504}
505505```
506506507507-```jsx{2,5}
507507+```jsx {2,5}
508508function Example(props) {
509509 const counter = props.counter;
510510 useEffect(() => {
···524524525525Here’s a [version of our counter example](https://codesandbox.io/s/rm7z22qnlp) that replicates the class behavior:
526526527527-```jsx{3,6-7,9-10}
527527+```jsx {3,6-7,9-10}
528528function Example() {
529529 const [count, setCount] = useState(0);
530530 const latestCount = useRef(count);
···588588589589Now 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:
590590591591-```jsx{8-11}
591591+```jsx {8-11}
592592// First render, props are {id: 10}
593593function Example() {
594594 // ...
···650650651651You should think of effects in a similar way. **`useEffect` lets you _synchronize_ things outside of the React tree according to our props and state.**
652652653653-```jsx{2-4}
653653+```jsx {2-4}
654654function Greeting({ name }) {
655655 useEffect(() => {
656656 document.title = 'Hello, ' + name;
···709709710710For example, maybe our component re-renders because of a state change:
711711712712-```jsx{11-13}
712712+```jsx {11-13}
713713function Greeting({ name }) {
714714 const [counter, setCounter] = useState(0);
715715···743743744744This is why if you want to avoid re-running effects unnecessarily, you can provide a dependency array (also known as “deps”) argument to `useEffect`:
745745746746-```jsx{3}
746746+```jsx {3}
747747 useEffect(() => {
748748 document.title = 'Hello, ' + name;
749749 }, [name]); // Our deps
···796796797797If deps contain every value used by the effect, React knows when to re-run it:
798798799799-```jsx{3}
799799+```jsx {3}
800800 useEffect(() => {
801801 document.title = 'Hello, ' + name;
802802 }, [name]);
···808808809809But if we specified `[]` for this effect, the new effect function wouldn’t run:
810810811811-```jsx{3}
811811+```jsx {3}
812812 useEffect(() => {
813813 document.title = 'Hello, ' + name;
814814 }, []); // Wrong: name is missing in deps
···822822823823For 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?
824824825825-```jsx{9}
825825+```jsx {9}
826826function Counter() {
827827 const [count, setCount] = useState(0);
828828···845845846846In 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:**
847847848848-```jsx{8,12,21-22}
848848+```jsx {8,12,21-22}
849849// First render, state is 0
850850function Counter() {
851851 // ...
···884884885885Our effect uses `count` — a value inside the component (but outside the effect):
886886887887-```jsx{1,5}
887887+```jsx {1,5}
888888 const count = // ...
889889890890 useEffect(() => {
···909909910910**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:
911911912912-```jsx{3,6}
912912+```jsx {3,6}
913913useEffect(() => {
914914 const id = setInterval(() => {
915915 setCount(count + 1);
···920920921921This 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)`:
922922923923-```jsx{8,12,24,28}
923923+```jsx {8,12,24,28}
924924// First render, state is 0
925925function Counter() {
926926 // ...
···972972973973We want to get rid of the `count` dependency in our effect.
974974975975-```jsx{3,6}
975975+```jsx {3,6}
976976 useEffect(() => {
977977 const id = setInterval(() => {
978978 setCount(count + 1);
···983983984984To 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`:
985985986986-```jsx{3}
986986+```jsx {3}
987987 useEffect(() => {
988988 const id = setInterval(() => {
989989 setCount(c => c + 1);
···1020102010211021Let’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:
1022102210231023-```jsx{7,10}
10231023+```jsx {7,10}
10241024function Counter() {
10251025 const [count, setCount] = useState(0);
10261026 const [step, setStep] = useState(1);
···1055105510561056Let’s trade the `step` dependency for a `dispatch` dependency in our effect:
1057105710581058-```jsx{1,6,9}
10581058+```jsx {1,6,9}
10591059const [state, dispatch] = useReducer(reducer, initialState);
10601060const { count, step } = state;
10611061···1077107710781078Instead 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:
1079107910801080-```jsx{8,9}
10801080+```jsx {8,9}
10811081const initialState = {
10821082 count: 0,
10831083 step: 1,
···1103110311041104In fact, we can! We can put *the reducer itself* inside our component to read props:
1105110511061106-```jsx{1,6}
11061106+```jsx {1,6}
11071107function Counter({ step }) {
11081108 const [count, dispatch] = useReducer(reducer, 0);
11091109···1138113811391139A common mistake is to think functions shouldn’t be dependencies. For example, this seems like it could work:
1140114011411141-```jsx{13}
11411141+```jsx {13}
11421142function SearchResults() {
11431143 const [data, setData] = useState({ hits: [] });
11441144···1186118611871187Now let’s say we later use some state or prop in one of these functions:
1188118811891189-```jsx{6}
11891189+```jsx {6}
11901190function SearchResults() {
11911191 const [query, setQuery] = useState('react');
11921192···1213121312141214Luckily, there is an easy solution to this problem. **If you only use some functions *inside* an effect, move them directly *into* that effect:**
1215121512161216-```jsx{4-12}
12161216+```jsx {4-12}
12171217function SearchResults() {
12181218 // ...
12191219 useEffect(() => {
···1239123912401240If 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:
1241124112421242-```jsx{6,15}
12421242+```jsx {6,15}
12431243function SearchResults() {
12441244 const [query, setQuery] = useState('react');
12451245···1302130213031303On 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:
1304130413051305-```jsx{2-5}
13051305+```jsx {2-5}
13061306function SearchResults() {
13071307 // 🔴 Re-triggers all effects on every render
13081308 function getFetchUrl(query) {
···1329132913301330**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:**
1331133113321332-```jsx{1-4}
13321332+```jsx {1-4}
13331333// ✅ Not affected by the data flow
13341334function getFetchUrl(query) {
13351335 return 'https://hn.algolia.com/api/v1/search?query=' + query;
···13551355Alternatively, you can wrap it into the [`useCallback` Hook](https://reactjs.org/docs/hooks-reference.html#usecallback):
135613561357135713581358-```jsx{2-5}
13581358+```jsx {2-5}
13591359function SearchResults() {
13601360 // ✅ Preserves identity when its own deps are the same
13611361 const getFetchUrl = useCallback((query) => {
···1382138213831383We'll immediately see that it's missing a `query` dependency:
1384138413851385-```jsx{5}
13851385+```jsx {5}
13861386function SearchResults() {
13871387 const [query, setQuery] = useState('react');
13881388 const getFetchUrl = useCallback(() => { // No query argument
···1394139413951395If I fix my `useCallback` deps to include `query`, any effect with `getFetchUrl` in deps will re-run whenever the `query` changes:
1396139613971397-```jsx{4-7}
13971397+```jsx {4-7}
13981398function SearchResults() {
13991399 const [query, setQuery] = useState('react');
14001400···1416141614171417This is just a consequence of embracing the data flow and the synchronization mindset. **The same solution works for function props passed from parents:**
1418141814191419-```jsx{4-8}
14191419+```jsx {4-8}
14201420function Parent() {
14211421 const [query, setQuery] = useState('react');
14221422···1446144614471447Interestingly, this pattern is broken with classes in a way that really shows the difference between the effect and lifecycle paradigms. Consider this translation:
1448144814491449-```jsx{5-8,18-20}
14491449+```jsx {5-8,18-20}
14501450class Parent extends Component {
14511451 state = {
14521452 query: 'react'
···1475147514761476You 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`:**
1477147714781478-```jsx{8-13}
14781478+```jsx {8-13}
14791479class Child extends Component {
14801480 state = {
14811481 data: null
···1515151515161516The 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:
1517151715181518-```jsx{10,22-24}
15181518+```jsx {10,22-24}
15191519class Parent extends Component {
15201520 state = {
15211521 query: 'react'
···1591159115921592As 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:
1593159315941594-```jsx{8-12}
15941594+```jsx {8-12}
15951595class Article extends Component {
15961596 state = {
15971597 article: null
···1622162216231623Alternatively, the easiest stopgap approach is to track it with a boolean:
1624162416251625-```jsx{5,9,16-18}
16251625+```jsx {5,9,16-18}
16261626function Article({ id }) {
16271627 const [article, setArticle] = useState(null);
16281628
···35353636Let’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:
37373838-```jsx{4,19}
3838+```jsx {4,19}
3939function getName(user) {
4040 let name = user.name;
4141 if (name === null) {
···70707171This 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`:
72727373-```jsx{4,19-21}
7373+```jsx {4,19-21}
7474function getName(user) {
7575 let name = user.name;
7676 if (name === null) {
···103103104104Instead 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:
105105106106-```jsx{4}
106106+```jsx {4}
107107function getName(user) {
108108 let name = user.name;
109109 if (name === null) {
···115115116116When 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:
117117118118-```jsx{3}
118118+```jsx {3}
119119try {
120120 makeFriends(arya, gendry);
121121} handle (effect) {
···127127128128This 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`:
129129130130-```jsx{5}
130130+```jsx {5}
131131try {
132132 makeFriends(arya, gendry);
133133} handle (effect) {
···139139140140This 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**. 🤯
141141142142-```jsx{4,6,16,18}
142142+```jsx {4,6,16,18}
143143function getName(user) {
144144 let name = user.name;
145145 if (name === null) {
···194194195195For a moment, let’s forget about `async / await` and get back to our example:
196196197197-```jsx{4,19-21}
197197+```jsx {4,19-21}
198198function getName(user) {
199199 let name = user.name;
200200 if (name === null) {
···223223224224It turns out, we can call `resume with` asynchronously from our effect handler without making any changes to `getName` or `makeFriends`:
225225226226-```jsx{19-23}
226226+```jsx {19-23}
227227function getName(user) {
228228 let name = user.name;
229229 if (name === null) {
···264264265265They let you write code that focuses on *what* you’re doing:
266266267267-```jsx{2,3,5,7,12}
267267+```jsx {2,3,5,7,12}
268268function enumerateFiles(dir) {
269269 const contents = perform OpenDirectory(dir);
270270 perform Log('Enumerating files in ', dir);
···282282283283And later wrap it with something that specifies *how*:
284284285285-```jsx{6-7,9-11,13-14}
285285+```jsx {6-7,9-11,13-14}
286286let files = [];
287287try {
288288 enumerateFiles('C:\\');
···323323324324Effect 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:
325325326326-```jsx{19-23}
326326+```jsx {19-23}
327327import { withFakeFileSystem } from 'fake-fs';
328328329329function withLogSnapshot(fn) {
+4-4
public/before-you-memo/index.md
···53535454If you look at the rendering code closer, you'll notice only a part of the returned tree actually cares about the current `color`:
55555656-```jsx{2,5-6}
5656+```jsx {2,5-6}
5757export default function App() {
5858 let [color, setColor] = useState('red');
5959 return (
···68686969So let's extract that part into a `Form` component and move state _down_ into it:
70707171-```jsx{4,11,14,15}
7171+```jsx {4,11,14,15}
7272export default function App() {
7373 return (
7474 <>
···97979898The 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>`:
9999100100-```jsx{2,4}
100100+```jsx {2,4}
101101export default function App() {
102102 let [color, setColor] = useState('red');
103103 return (
···126126127127The answer is remarkably plain:
128128129129-```jsx{4,5,10,15}
129129+```jsx {4,5,10,15}
130130export default function App() {
131131 return (
132132 <ColorPicker>
···112112113113Let’s look closely at the `showMessage` method in our class:
114114115115-```jsx{3}
115115+```jsx {3}
116116class ProfilePage extends React.Component {
117117 showMessage = () => {
118118 alert('Followed ' + this.props.user);
···137137138138One 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:
139139140140-```jsx{2,7}
140140+```jsx {2,7}
141141class ProfilePage extends React.Component {
142142 showMessage = (user) => {
143143 alert('Followed ' + user);
···162162163163Perhaps, we could *bind* the methods in the constructor?
164164165165-```jsx{4-5}
165165+```jsx {4-5}
166166class ProfilePage extends React.Component {
167167 constructor(props) {
168168 super(props);
···190190191191This means that if you close over props or state from a particular render, you can always count on them staying exactly the same:
192192193193-```jsx{3,4,9}
193193+```jsx {3,4,9}
194194class ProfilePage extends React.Component {
195195 render() {
196196 // Capture the props!
···246246247247It’s a bit more obvious if you destructure `props` in the function definition:
248248249249-```jsx{1,3}
249249+```jsx {1,3}
250250function ProfilePage({ user }) {
251251 const showMessage = () => {
252252 alert('Followed ' + user);
···329329330330By 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:
331331332332-```jsx{3,6,15}
332332+```jsx {3,6,15}
333333function MessageThread() {
334334 const [message, setMessage] = useState('');
335335 const latestMessage = useRef('');
···354354355355Generally, 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:
356356357357-```jsx{4-8,11}
357357+```jsx {4-8,11}
358358function MessageThread() {
359359 const [message, setMessage] = useState('');
360360
···77777878First, 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:
79798080-```jsx{5}
8080+```jsx {5}
8181// If Greeting is a function
8282const result = Greeting(props); // <p>Hello</p>
8383···116116117117The `new` operator also makes anything we put on `Person.prototype` available on the `fred` object:
118118119119-```jsx{4-6,9}
119119+```jsx {4-6,9}
120120function Person(name) {
121121 this.name = name;
122122}
···244244245245This 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:
246246247247-```jsx{2,6,7}
247247+```jsx {2,6,7}
248248class Friends extends React.Component {
249249 render() {
250250 const friends = this.props.friends;
···297297298298However, 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:
299299300300-```jsx{1-2,7-8,17-18}
300300+```jsx {1-2,7-8,17-18}
301301// Created lazily
302302var zeroVector = null;
303303···371371372372What’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!**
373373374374-```jsx{8}
374374+```jsx {8}
375375function Person(name) {
376376 this.name = name;
377377}
···409409410410With 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`:
411411412412-```jsx{1,9,13}
412412+```jsx {1,9,13}
413413class Greeting extends React.Component {
414414 render() {
415415 return <p>Hello</p>;
···447447448448Since 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:
449449450450-```jsx{3,4}
450450+```jsx {3,4}
451451// `__proto__` chain
452452new Greeting()
453453 → Greeting.prototype // 🕵️ We start here
+3-3
public/how-does-setstate-know-what-to-do/index.md
···7788When you call `setState` in a component, what do you think happens?
991010-```jsx{11}
1010+```jsx {11}
1111import React from 'react';
1212import ReactDOM from 'react-dom';
1313···112112**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:
113113114114115115-```jsx{4,9,14}
115115+```jsx {4,9,14}
116116// Inside React DOM
117117const inst = new YourComponent();
118118inst.props = props;
···172172173173And individual renderers set the dispatcher before rendering your component:
174174175175-```jsx{3,8-9}
175175+```jsx {3,8-9}
176176// In React DOM
177177const prevDispatcher = React.__currentDispatcher;
178178React.__currentDispatcher = ReactDOMDispatcher;
···30303131Without further ado, here’s a counter that increments every second:
32323333-```jsx{6-9}
3333+```jsx {6-9}
3434import React, { useState, useEffect, useRef } from 'react';
35353636function Counter() {
···128128129129So how would you do this with `setInterval` in a class? I ended up with this:
130130131131-```jsx{7-26}
131131+```jsx {7-26}
132132class Counter extends React.Component {
133133 state = {
134134 count: 0,
···179179180180<font size="50">🥁🥁🥁</font>
181181182182-```jsx{5-8}
182182+```jsx {5-8}
183183function Counter() {
184184 let [count, setCount] = useState(0);
185185 let [delay, setDelay] = useState(1000);
···208208209209Unlike the class version, there is no complexity gap for “upgrading” the `useInterval` Hook example to have a dynamically adjusted delay:
210210211211-```jsx{4,9}
211211+```jsx {4,9}
212212 // Constant delay
213213 useInterval(() => {
214214 setCount(count + 1);
···226226227227What if I want to temporarily *pause* my interval? I can do this with state too:
228228229229-```jsx{6}
229229+```jsx {6}
230230 const [delay, setDelay] = useState(1000);
231231 const [isRunning, setIsRunning] = useState(true);
232232···260260261261Now 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:
262262263263-```jsx{4-9}
263263+```jsx {4-9}
264264function Counter() {
265265 let [count, setCount] = useState(0);
266266···304304305305You 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:
306306307307-```jsx{3}
307307+```jsx {3}
308308useEffect(() => {
309309 document.title = `You clicked ${count} times`;
310310}, [count]);
···316316317317In 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:
318318319319-```jsx{9}
319319+```jsx {9}
320320function Counter() {
321321 let [count, setCount] = useState(0);
322322···364364365365Hooks let us apply the same declarative approach to effects:
366366367367-```jsx{4}
367367+```jsx {4}
368368 // Describes every interval state
369369 useInterval(() => {
370370 setCount(count + 1);
···420420421421`useRef()` returns a plain object with a mutable `current` property that’s shared between renders. We can save the *latest* interval callback into it:
422422423423-```jsx{8}
423423+```jsx {8}
424424 function callback() {
425425 // Can read fresh props, state, etc.
426426 setCount(count + 1);
···434434435435And then we can read and call it from inside our interval:
436436437437-```jsx{3,8}
437437+```jsx {3,8}
438438 useEffect(() => {
439439 function tick() {
440440 savedCallback.current();
···449449450450Here’s a complete working solution:
451451452452-```jsx{10,15}
452452+```jsx {10,15}
453453function Counter() {
454454 const [count, setCount] = useState(0);
455455 const savedCallback = useRef();
···487487488488Ideally, I just want to write this:
489489490490-```jsx{4-6}
490490+```jsx {4-6}
491491function Counter() {
492492 const [count, setCount] = useState(0);
493493···534534535535 Now that the `delay` can change between renders, I need to declare it in the dependencies of my interval effect:
536536537537-```jsx{8}
537537+```jsx {8}
538538 useEffect(() => {
539539 function tick() {
540540 savedCallback.current();
···586586587587Say we want to be able to pause our interval by passing `null` as the `delay`:
588588589589-```jsx{6}
589589+```jsx {6}
590590 const [delay, setDelay] = useState(1000);
591591 const [isRunning, setIsRunning] = useState(true);
592592···597597598598How do we implement this? The answer is: by not setting up an interval.
599599600600-```jsx{6}
600600+```jsx {6}
601601 useEffect(() => {
602602 function tick() {
603603 savedCallback.current();
···622622623623
624624625625-```jsx{10-15}
625625+```jsx {10-15}
626626function Counter() {
627627 const [delay, setDelay] = useState(1000);
628628 const [count, setCount] = useState(0);
+1-1
public/my-wishlist-for-hot-reloading/index.md
···59596060For 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:
61616262-```jsx{4}
6262+```jsx {4}
6363// Reassigns the latest version
6464window.latest_Button = function(props) {
6565 // Your actual code is moved here by a plugin
+23-23
public/react-as-a-ui-runtime/index.md
···134134135135React 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:
136136137137-```jsx{3,4}
137137+```jsx {3,4}
138138// Somewhere in the ReactDOM renderer (simplified)
139139function createHostInstance(reactElement) {
140140 let domNode = document.createElement(reactElement.type);
···145145146146In our example, effectively React will do this:
147147148148-```jsx{1,2}
148148+```jsx {1,2}
149149let domNode = document.createElement('button');
150150domNode.className = 'blue';
151151···158158159159What happens if we call `ReactDOM.render()` twice with the same container?
160160161161-```jsx{2,11}
161161+```jsx {2,11}
162162ReactDOM.render(
163163 <button className="blue" />,
164164 document.getElementById('container')
···208208209209Here is an example with comments showing roughly what React does:
210210211211-```jsx{9,10,16,26,27}
211211+```jsx {9,10,16,26,27}
212212// let domNode = document.createElement('button');
213213// domNode.className = 'blue';
214214// domContainer.appendChild(domNode);
···250250251251Say we want to first show only an input, but later render a message before it:
252252253253-```jsx{12}
253253+```jsx {12}
254254// First render
255255ReactDOM.render(
256256 <dialog>
···277277278278So effectively the update code executed by React would be like:
279279280280-```jsx{1,2,8,9}
280280+```jsx {1,2,8,9}
281281let oldInputNode = dialogNode.firstChild;
282282dialogNode.removeChild(oldInputNode);
283283···312312313313This 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:
314314315315-```jsx{12-15}
315315+```jsx {12-15}
316316function Form({ showMessage }) {
317317 let message = null;
318318 if (showMessage) {
···392392393393**This is why React nags you to specify a special property called `key` every time you include an array of elements in your output:**
394394395395-```jsx{5}
395395+```jsx {5}
396396function ShoppingList({ list }) {
397397 return (
398398 <form>
···454454455455However, *local mutation* is absolutely fine:
456456457457-```jsx{2,5}
457457+```jsx {2,5}
458458function FriendList({ friends }) {
459459 let items = [];
460460 for (let i = 0; i < friends.length; i++) {
···602602603603Consider this component putting `<Comments>` inside a `<Page>`:
604604605605-```jsx{11}
605605+```jsx {11}
606606function Story({ currentUser }) {
607607 // return {
608608 // type: Page,
···621621622622The `Page` component can render the children given to it inside some `Layout`:
623623624624-```jsx{4}
624624+```jsx {4}
625625function Page({ user, children }) {
626626 return (
627627 <Layout>
···635635636636But what if it has an early exit condition?
637637638638-```jsx{2-4}
638638+```jsx {2-4}
639639function Page({ user, children }) {
640640 if (!user.isLoggedIn) {
641641 return <h1>Please log in</h1>;
···650650651651If we called `Comments()` as a function, it would execute immediately regardless of whether `Page` wants to render them or not:
652652653653-```jsx{4,8}
653653+```jsx {4,8}
654654// {
655655// type: Page,
656656// props: {
···664664665665But if we pass a React element, we don’t execute `Comments` ourselves at all:
666666667667-```jsx{4,8}
667667+```jsx {4,8}
668668// {
669669// type: Page,
670670// props: {
···689689690690We call these features *Hooks*. For example, `useState` is a Hook.
691691692692-```jsx{2,6,7}
692692+```jsx {2,6,7}
693693function Example() {
694694 const [count, setCount] = useState(0);
695695···723723724724When 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:
725725726726-```jsx{5}
726726+```jsx {5}
727727function Row({ item }) {
728728 // ...
729729}
···754754755755Several components may want to update state in response to the same event. This example is contrived but it illustrates a common pattern:
756756757757-```jsx{4,14}
757757+```jsx {4,14}
758758function Parent() {
759759 let [count, setCount] = useState(0);
760760 return (
···779779780780If React immediately re-rendered components in response to `setState` calls, we’d end up rendering the child twice:
781781782782-```jsx{4,8}
782782+```jsx {4,8}
783783*** Entering React's browser click event handler ***
784784Child (onClick)
785785 - setState
···916916917917In React, this is done by declaring an effect:
918918919919-```jsx{4-6}
919919+```jsx {4-6}
920920function Example() {
921921 const [count, setCount] = useState(0);
922922···952952953953Sometimes, 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:
954954955955-```jsx{3}
955955+```jsx {3}
956956 useEffect(() => {
957957 document.title = `You clicked ${count} times`;
958958 }, [count]);
···981981982982To solve this, make sure that if you specify the dependency array, it includes **all** things that can change, including the functions:
983983984984-```jsx{4}
984984+```jsx {4}
985985 useEffect(() => {
986986 DataSource.addSubscription(handleChange);
987987 return () => DataSource.removeSubscription(handleChange);
···996996997997Since Hooks like `useState` and `useEffect` are function calls, we can compose them into our own Hooks:
998998999999-```jsx{2,8}
999999+```jsx {2,8}
10001000function MyResponsiveComponent() {
10011001 const width = useWindowWidth(); // Our custom Hook
10021002 return (
···1027102710281028If `use` *were* a syntax, it would make sense for it to be at the top level:
1029102910301030-```jsx{3}
10301030+```jsx {3}
10311031// 😉 Note: not a real syntax
10321032component Example(props) {
10331033 const [count, setCount] = use State(0);
+1-1
public/the-bug-o-notation/index.md
···116116117117This code might not look too different. It’s even a bit more verbose. But it is *dramatically* simpler to debug because of this line:
118118119119-```jsx{3}
119119+```jsx {3}
120120function setState(nextState) {
121121 // Clear all existing children
122122 formStatus.innerHTML = '';
+12-12
public/why-do-hooks-rely-on-call-order/index.md
···35353636There 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:
37373838-```jsx{2,3,4}
3838+```jsx {2,3,4}
3939function Form() {
4040 const [name, setName] = useState('Mary'); // State variable 1
4141 const [surname, setSurname] = useState('Poppins'); // State variable 2
···103103104104But 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:
105105106106-```jsx{6-7}
106106+```jsx {6-7}
107107function Form() {
108108 // Declare some state variables directly in component body
109109 const [name, setName] = useState('Mary');
···174174175175This proposal seems to work for extracting the `useWindowWidth()` Hook:
176176177177-```jsx{4,11-17}
177177+```jsx {4,11-17}
178178// ⚠️ This is NOT the React Hooks API
179179function Form() {
180180 // ...
···196196197197But if we attempt to extract input handling, it would fail:
198198199199-```jsx{4,5,19-29}
199199+```jsx {4,5,19-29}
200200// ⚠️ This is NOT the React Hooks API
201201function Form() {
202202 // ...
···251251252252Two custom Hooks like `useWindowWidth()` and `useNetworkStatus()` might want to use the same custom Hook like `useSubscription()` under the hood:
253253254254-```jsx{12,23-27,32-42}
254254+```jsx {12,23-27,32-42}
255255function StatusMessage() {
256256 const width = useWindowWidth();
257257 const isOnline = useNetworkStatus();
···330330331331One 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:
332332333333-```jsx{5,6}
333333+```jsx {5,6}
334334/*******************
335335 * useFormInput.js *
336336 ******************/
···354354355355Additionally, 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:
356356357357-```jsx{2,3,7,8}
357357+```jsx {2,3,7,8}
358358// ⚠️ This is NOT the React Hooks API
359359const useNameFormInput = createUseFormInput();
360360const useSurnameFormInput = createUseFormInput();
···386386387387The idea is that we could *compose* keys every time we write a custom Hook. Something like this:
388388389389-```jsx{4,5,16,17}
389389+```jsx {4,5,16,17}
390390// ⚠️ This is NOT the React Hooks API
391391function Form() {
392392 // ...
···423423424424What does this code mean exactly?
425425426426-```jsx{3,4}
426426+```jsx {3,4}
427427// ⚠️ This is NOT the React Hooks API
428428function Counter(props) {
429429 if (props.isActive) {
···442442443443If conditional state gets preserved, what about an effect?
444444445445-```jsx{5-8}
445445+```jsx {5-8}
446446// ⚠️ This is NOT the React Hooks API
447447function Counter(props) {
448448 if (props.isActive) {
···487487488488Here is a hypothetical example of a message recipient picker that shows whether the currently chosen friend is online:
489489490490-```jsx{8,9}
490490+```jsx {8,9}
491491const friendList = [
492492 { id: 1, name: 'Phoebe' },
493493 { id: 2, name: 'Rachel' },
···532532533533This works because we can pass the return value of the `useState()` Hook to the `useFriendStatus()` Hook:
534534535535-```jsx{2}
535535+```jsx {2}
536536 const [recipientID, setRecipientID] = useState(1);
537537 const isRecipientOnline = useFriendStatus(recipientID);
538538```
···23232424And 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.
25252626-```jsx{9}
2626+```jsx {9}
2727{
2828 type: 'marquee',
2929 props: {
···105105106106However, **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:
107107108108-```jsx{2-10,15}
108108+```jsx {2-10,15}
109109// Server could have a hole that lets user store JSON
110110let expectedTextButGotJSON = {
111111 type: 'div',
···128128129129The fix in React 0.14 was to [tag every React element with a Symbol](https://github.com/facebook/react/pull/4832):
130130131131-```jsx{9}
131131+```jsx {9}
132132{
133133 type: 'marquee',
134134 props: {
+3-3
public/why-do-we-write-super-props/index.md
···15151616I wrote `super(props)` more times in my life than I’d like to know:
17171818-```jsx{3}
1818+```jsx {3}
1919class Checkbox extends React.Component {
2020 constructor(props) {
2121 super(props);
···38383939But let’s get back to this example using only ES2015 features:
40404141-```jsx{3}
4141+```jsx {3}
4242class Checkbox extends React.Component {
4343 constructor(props) {
4444 super(props);
···145145146146**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:
147147148148-```jsx{14}
148148+```jsx {14}
149149// Inside React
150150class Component {
151151 constructor(props) {
+4-4
public/why-isnt-x-a-hook/index.md
···61616262Hooks are useful because you can pass values *between* Hooks:
63636464-```jsx{4,12,14}
6464+```jsx {4,12,14}
6565function useWindowWidth() {
6666 const [width, setWidth] = useState(window.innerWidth);
6767 // ...
···108108109109`React.memo()` takes a component and returns a component:
110110111111-```jsx{4}
111111+```jsx {4}
112112function Button(props) {
113113 // ...
114114}
···138138139139Let’s say we try to put `useBailout()` in two custom Hooks:
140140141141-```jsx{4,5,19,20}
141141+```jsx {4,5,19,20}
142142function useFriendStatus(friendID) {
143143 const [isOnline, setIsOnline] = useState(null);
144144···173173Now what happens if you use them both in the same component?
174174175175176176-```jsx{2,3}
176176+```jsx {2,3}
177177function ChatThread({ friendID, isTyping }) {
178178 const width = useWindowWidth();
179179 const isOnline = useFriendStatus(friendID);
+24-24
public/writing-resilient-components/index.md
···91919292However, a common mistake when learning React is to copy props into state:
93939494-```jsx{3,6}
9494+```jsx {3,6}
9595class Button extends React.Component {
9696 state = {
9797 color: this.props.color
···133133134134Computed 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:
135135136136-```jsx{3,9}
136136+```jsx {3,9}
137137class Button extends React.Component {
138138 state = {
139139 textColor: slowlyCalculateTextColor(this.props.color)
···153153154154This 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`:
155155156156-```jsx{1,3}
156156+```jsx {1,3}
157157class Button extends React.PureComponent {
158158 render() {
159159 const textColor = slowlyCalculateTextColor(this.props.color);
···173173174174However, 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`:
175175176176-```jsx{5-12}
176176+```jsx {5-12}
177177class Button extends React.Component {
178178 state = {
179179 textColor: slowlyCalculateTextColor(this.props.color)
···207207208208With 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:
209209210210-```jsx{2-5}
210210+```jsx {2-5}
211211function Button({ color, children }) {
212212 const textColor = useMemo(
213213 () => slowlyCalculateTextColor(color),
···235235236236Consider this React component:
237237238238-```jsx{5-7}
238238+```jsx {5-7}
239239class SearchResults extends React.Component {
240240 state = {
241241 data: null
···258258259259A 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:
260260261261-```jsx{2}
261261+```jsx {2}
262262 getFetchUrl() {
263263 return 'http://myapi/results?query' + this.props.query;
264264 }
···275275* Make sure that whenever those props change, we re-run the side effect.
276276 - We can do this by adding the `componentDidUpdate` method.
277277278278-```jsx{8-12,18}
278278+```jsx {8-12,18}
279279class SearchResults extends React.Component {
280280 state = {
281281 data: null
···305305306306However, 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`:
307307308308-```jsx{4,21}
308308+```jsx {4,21}
309309class SearchResults extends React.Component {
310310 state = {
311311 data: null,
···350350351351Let’s fix our component to handle updates to the `currentPage` state:
352352353353-```jsx{11,24}
353353+```jsx {11,24}
354354class SearchResults extends React.Component {
355355 state = {
356356 data: null,
···391391392392However, 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:
393393394394-```jsx{13-14,19}
394394+```jsx {13-14,19}
395395function SearchResults({ query }) {
396396 const [data, setData] = useState(null);
397397 const [currentPage, setCurrentPage] = useState(0);
···442442443443**However, if you try to “optimize” a component by writing your own comparison, you may mistakenly forget to compare function props:**
444444445445-```jsx{2-5,7}
445445+```jsx {2-5,7}
446446class Button extends React.Component {
447447 shouldComponentUpdate(prevProps) {
448448 // 🔴 Doesn't compare this.props.onClick
···464464465465It 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:
466466467467-```jsx{2-4,9-11}
467467+```jsx {2-4,9-11}
468468class MyForm extends React.Component {
469469 handleClick = () => { // ✅ Always the same function
470470 // Do something
···484484485485So 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:
486486487487-```jsx{6,13-15}
487487+```jsx {6,13-15}
488488class MyForm extends React.Component {
489489 state = {
490490 isEnabled: true
···513513514514This could get even more confusing if the function identity itself depends on something that could change over time, like `draft.content` in this example:
515515516516-```jsx{6-7}
516516+```jsx {6-7}
517517 drafts.map(draft =>
518518 <Button
519519 color='blue'
···533533534534I 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:
535535536536-```jsx{11}
536536+```jsx {11}
537537function Button({ onClick, color, children }) {
538538 const textColor = slowlyCalculateTextColor(color);
539539 return (
···553553554554If you insist on a custom comparison, **make sure that you don’t skip functions:**
555555556556-```jsx{5}
556556+```jsx {5}
557557 shouldComponentUpdate(prevProps) {
558558 // ✅ Compares this.props.onClick
559559 return (
···586586587587How can one violate this principle? React doesn’t make it very easy — but you can do it by using the legacy `componentWillReceiveProps` lifecycle method:
588588589589-```jsx{5-8}
589589+```jsx {5-8}
590590class TextInput extends React.Component {
591591 state = {
592592 value: ''
···659659660660To stress-test your component, you can temporarily add this code to its parent:
661661662662-```jsx{2}
662662+```jsx {2}
663663componentDidMount() {
664664 // Don't forget to remove this immediately!
665665 setInterval(() => this.forceUpdate(), 100);
···674674675675This code should work, right?
676676677677-```jsx{1-2}
677677+```jsx {1-2}
678678// 🤔 Should prevent unnecessary re-renders... right?
679679class TextInput extends React.PureComponent {
680680 state = {
···702702703703However, 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:
704704705705-```jsx{2}
705705+```jsx {2}
706706<TextInput
707707 style={{opacity: someValueFromState}}
708708 value={
···727727728728It’s easy to check for these problems. Just for fun, try to render your app twice:
729729730730-```jsx{3,4}
730730+```jsx {3,4}
731731ReactDOM.render(
732732 <>
733733 <MyApp />
···743743744744An example of a problematic pattern I’ve written myself a few times is performing global state “cleanup” in `componentWillUnmount`:
745745746746-```jsx{2-3}
746746+```jsx {2-3}
747747componentWillUnmount() {
748748 // Resets something in Redux store
749749 this.props.resetForm();
···752752753753Of 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:
754754755755-```jsx{2-3}
755755+```jsx {2-3}
756756componentDidMount() {
757757 // Resets something in Redux store
758758 this.props.resetForm();