···7475Here’s a counter. Look at the highlighted line closely:
7677-```jsx{6}
78function Counter() {
79 const [count, setCount] = useState(0);
80···102103The 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:
104105-```jsx{3,11,19}
106// During first render
107function Counter() {
108 const count = 0; // Returned by useState()
···148149Look at this example. It shows an alert with the `count` after three seconds:
150151-```jsx{4-8,16-18}
152function Counter() {
153 const [count, setCount] = useState(0);
154···204205This is not specific to React — regular functions work in a similar way:
206207-```jsx{2}
208function sayHi(person) {
209 const name = person.name;
210 setTimeout(() => {
···226227This 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`:
228229-```jsx{3,15,27}
230// During first render
231function Counter() {
232 const count = 0; // Returned by useState()
···266267So effectively, each render returns its own “version” of `handleAlertClick`. Each of those versions “remembers” its own `count`:
268269-```jsx{6,10,19,23,32,36}
270// During first render
271function Counter() {
272 // ...
···319320Let’s go back to an example from [the docs](https://reactjs.org/docs/hooks-effect.html):
321322-```jsx{4-6}
323function Counter() {
324 const [count, setCount] = useState(0);
325···350351Each version “sees” the `count` value from the render that it “belongs” to:
352353-```jsx{5-8,17-20,29-32}
354// During first render
355function Counter() {
356 // ...
···433434Let’s try a thought experiment. Consider this code:
435436-```jsx{4-8}
437function Counter() {
438 const [count, setCount] = useState(0);
439···493494So these two examples are equivalent:
495496-```jsx{4}
497function Example(props) {
498 useEffect(() => {
499 setTimeout(() => {
···504}
505```
506507-```jsx{2,5}
508function Example(props) {
509 const counter = props.counter;
510 useEffect(() => {
···524525Here’s a [version of our counter example](https://codesandbox.io/s/rm7z22qnlp) that replicates the class behavior:
526527-```jsx{3,6-7,9-10}
528function Example() {
529 const [count, setCount] = useState(0);
530 const latestCount = useRef(count);
···588589Now 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:
590591-```jsx{8-11}
592// First render, props are {id: 10}
593function Example() {
594 // ...
···650651You should think of effects in a similar way. **`useEffect` lets you _synchronize_ things outside of the React tree according to our props and state.**
652653-```jsx{2-4}
654function Greeting({ name }) {
655 useEffect(() => {
656 document.title = 'Hello, ' + name;
···709710For example, maybe our component re-renders because of a state change:
711712-```jsx{11-13}
713function Greeting({ name }) {
714 const [counter, setCounter] = useState(0);
715···743744This is why if you want to avoid re-running effects unnecessarily, you can provide a dependency array (also known as “deps”) argument to `useEffect`:
745746-```jsx{3}
747 useEffect(() => {
748 document.title = 'Hello, ' + name;
749 }, [name]); // Our deps
···796797If deps contain every value used by the effect, React knows when to re-run it:
798799-```jsx{3}
800 useEffect(() => {
801 document.title = 'Hello, ' + name;
802 }, [name]);
···808809But if we specified `[]` for this effect, the new effect function wouldn’t run:
810811-```jsx{3}
812 useEffect(() => {
813 document.title = 'Hello, ' + name;
814 }, []); // Wrong: name is missing in deps
···822823For 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?
824825-```jsx{9}
826function Counter() {
827 const [count, setCount] = useState(0);
828···845846In 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:**
847848-```jsx{8,12,21-22}
849// First render, state is 0
850function Counter() {
851 // ...
···884885Our effect uses `count` — a value inside the component (but outside the effect):
886887-```jsx{1,5}
888 const count = // ...
889890 useEffect(() => {
···909910**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:
911912-```jsx{3,6}
913useEffect(() => {
914 const id = setInterval(() => {
915 setCount(count + 1);
···920921This 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)`:
922923-```jsx{8,12,24,28}
924// First render, state is 0
925function Counter() {
926 // ...
···972973We want to get rid of the `count` dependency in our effect.
974975-```jsx{3,6}
976 useEffect(() => {
977 const id = setInterval(() => {
978 setCount(count + 1);
···983984To 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`:
985986-```jsx{3}
987 useEffect(() => {
988 const id = setInterval(() => {
989 setCount(c => c + 1);
···10201021Let’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:
10221023-```jsx{7,10}
1024function Counter() {
1025 const [count, setCount] = useState(0);
1026 const [step, setStep] = useState(1);
···10551056Let’s trade the `step` dependency for a `dispatch` dependency in our effect:
10571058-```jsx{1,6,9}
1059const [state, dispatch] = useReducer(reducer, initialState);
1060const { count, step } = state;
1061···10771078Instead 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:
10791080-```jsx{8,9}
1081const initialState = {
1082 count: 0,
1083 step: 1,
···11031104In fact, we can! We can put *the reducer itself* inside our component to read props:
11051106-```jsx{1,6}
1107function Counter({ step }) {
1108 const [count, dispatch] = useReducer(reducer, 0);
1109···11381139A common mistake is to think functions shouldn’t be dependencies. For example, this seems like it could work:
11401141-```jsx{13}
1142function SearchResults() {
1143 const [data, setData] = useState({ hits: [] });
1144···11861187Now let’s say we later use some state or prop in one of these functions:
11881189-```jsx{6}
1190function SearchResults() {
1191 const [query, setQuery] = useState('react');
1192···12131214Luckily, there is an easy solution to this problem. **If you only use some functions *inside* an effect, move them directly *into* that effect:**
12151216-```jsx{4-12}
1217function SearchResults() {
1218 // ...
1219 useEffect(() => {
···12391240If 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:
12411242-```jsx{6,15}
1243function SearchResults() {
1244 const [query, setQuery] = useState('react');
1245···13021303On 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:
13041305-```jsx{2-5}
1306function SearchResults() {
1307 // 🔴 Re-triggers all effects on every render
1308 function getFetchUrl(query) {
···13291330**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:**
13311332-```jsx{1-4}
1333// ✅ Not affected by the data flow
1334function getFetchUrl(query) {
1335 return 'https://hn.algolia.com/api/v1/search?query=' + query;
···1355Alternatively, you can wrap it into the [`useCallback` Hook](https://reactjs.org/docs/hooks-reference.html#usecallback):
135613571358-```jsx{2-5}
1359function SearchResults() {
1360 // ✅ Preserves identity when its own deps are the same
1361 const getFetchUrl = useCallback((query) => {
···13821383We'll immediately see that it's missing a `query` dependency:
13841385-```jsx{5}
1386function SearchResults() {
1387 const [query, setQuery] = useState('react');
1388 const getFetchUrl = useCallback(() => { // No query argument
···13941395If I fix my `useCallback` deps to include `query`, any effect with `getFetchUrl` in deps will re-run whenever the `query` changes:
13961397-```jsx{4-7}
1398function SearchResults() {
1399 const [query, setQuery] = useState('react');
1400···14161417This is just a consequence of embracing the data flow and the synchronization mindset. **The same solution works for function props passed from parents:**
14181419-```jsx{4-8}
1420function Parent() {
1421 const [query, setQuery] = useState('react');
1422···14461447Interestingly, this pattern is broken with classes in a way that really shows the difference between the effect and lifecycle paradigms. Consider this translation:
14481449-```jsx{5-8,18-20}
1450class Parent extends Component {
1451 state = {
1452 query: 'react'
···14751476You 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`:**
14771478-```jsx{8-13}
1479class Child extends Component {
1480 state = {
1481 data: null
···15151516The 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:
15171518-```jsx{10,22-24}
1519class Parent extends Component {
1520 state = {
1521 query: 'react'
···15911592As 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:
15931594-```jsx{8-12}
1595class Article extends Component {
1596 state = {
1597 article: null
···16221623Alternatively, the easiest stopgap approach is to track it with a boolean:
16241625-```jsx{5,9,16-18}
1626function Article({ id }) {
1627 const [article, setArticle] = useState(null);
1628
···7475Here’s a counter. Look at the highlighted line closely:
7677+```jsx {6}
78function Counter() {
79 const [count, setCount] = useState(0);
80···102103The 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:
104105+```jsx {3,11,19}
106// During first render
107function Counter() {
108 const count = 0; // Returned by useState()
···148149Look at this example. It shows an alert with the `count` after three seconds:
150151+```jsx {4-8,16-18}
152function Counter() {
153 const [count, setCount] = useState(0);
154···204205This is not specific to React — regular functions work in a similar way:
206207+```jsx {2}
208function sayHi(person) {
209 const name = person.name;
210 setTimeout(() => {
···226227This 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`:
228229+```jsx {3,15,27}
230// During first render
231function Counter() {
232 const count = 0; // Returned by useState()
···266267So effectively, each render returns its own “version” of `handleAlertClick`. Each of those versions “remembers” its own `count`:
268269+```jsx {6,10,19,23,32,36}
270// During first render
271function Counter() {
272 // ...
···319320Let’s go back to an example from [the docs](https://reactjs.org/docs/hooks-effect.html):
321322+```jsx {4-6}
323function Counter() {
324 const [count, setCount] = useState(0);
325···350351Each version “sees” the `count` value from the render that it “belongs” to:
352353+```jsx {5-8,17-20,29-32}
354// During first render
355function Counter() {
356 // ...
···433434Let’s try a thought experiment. Consider this code:
435436+```jsx {4-8}
437function Counter() {
438 const [count, setCount] = useState(0);
439···493494So these two examples are equivalent:
495496+```jsx {4}
497function Example(props) {
498 useEffect(() => {
499 setTimeout(() => {
···504}
505```
506507+```jsx {2,5}
508function Example(props) {
509 const counter = props.counter;
510 useEffect(() => {
···524525Here’s a [version of our counter example](https://codesandbox.io/s/rm7z22qnlp) that replicates the class behavior:
526527+```jsx {3,6-7,9-10}
528function Example() {
529 const [count, setCount] = useState(0);
530 const latestCount = useRef(count);
···588589Now 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:
590591+```jsx {8-11}
592// First render, props are {id: 10}
593function Example() {
594 // ...
···650651You should think of effects in a similar way. **`useEffect` lets you _synchronize_ things outside of the React tree according to our props and state.**
652653+```jsx {2-4}
654function Greeting({ name }) {
655 useEffect(() => {
656 document.title = 'Hello, ' + name;
···709710For example, maybe our component re-renders because of a state change:
711712+```jsx {11-13}
713function Greeting({ name }) {
714 const [counter, setCounter] = useState(0);
715···743744This is why if you want to avoid re-running effects unnecessarily, you can provide a dependency array (also known as “deps”) argument to `useEffect`:
745746+```jsx {3}
747 useEffect(() => {
748 document.title = 'Hello, ' + name;
749 }, [name]); // Our deps
···796797If deps contain every value used by the effect, React knows when to re-run it:
798799+```jsx {3}
800 useEffect(() => {
801 document.title = 'Hello, ' + name;
802 }, [name]);
···808809But if we specified `[]` for this effect, the new effect function wouldn’t run:
810811+```jsx {3}
812 useEffect(() => {
813 document.title = 'Hello, ' + name;
814 }, []); // Wrong: name is missing in deps
···822823For 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?
824825+```jsx {9}
826function Counter() {
827 const [count, setCount] = useState(0);
828···845846In 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:**
847848+```jsx {8,12,21-22}
849// First render, state is 0
850function Counter() {
851 // ...
···884885Our effect uses `count` — a value inside the component (but outside the effect):
886887+```jsx {1,5}
888 const count = // ...
889890 useEffect(() => {
···909910**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:
911912+```jsx {3,6}
913useEffect(() => {
914 const id = setInterval(() => {
915 setCount(count + 1);
···920921This 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)`:
922923+```jsx {8,12,24,28}
924// First render, state is 0
925function Counter() {
926 // ...
···972973We want to get rid of the `count` dependency in our effect.
974975+```jsx {3,6}
976 useEffect(() => {
977 const id = setInterval(() => {
978 setCount(count + 1);
···983984To 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`:
985986+```jsx {3}
987 useEffect(() => {
988 const id = setInterval(() => {
989 setCount(c => c + 1);
···10201021Let’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:
10221023+```jsx {7,10}
1024function Counter() {
1025 const [count, setCount] = useState(0);
1026 const [step, setStep] = useState(1);
···10551056Let’s trade the `step` dependency for a `dispatch` dependency in our effect:
10571058+```jsx {1,6,9}
1059const [state, dispatch] = useReducer(reducer, initialState);
1060const { count, step } = state;
1061···10771078Instead 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:
10791080+```jsx {8,9}
1081const initialState = {
1082 count: 0,
1083 step: 1,
···11031104In fact, we can! We can put *the reducer itself* inside our component to read props:
11051106+```jsx {1,6}
1107function Counter({ step }) {
1108 const [count, dispatch] = useReducer(reducer, 0);
1109···11381139A common mistake is to think functions shouldn’t be dependencies. For example, this seems like it could work:
11401141+```jsx {13}
1142function SearchResults() {
1143 const [data, setData] = useState({ hits: [] });
1144···11861187Now let’s say we later use some state or prop in one of these functions:
11881189+```jsx {6}
1190function SearchResults() {
1191 const [query, setQuery] = useState('react');
1192···12131214Luckily, there is an easy solution to this problem. **If you only use some functions *inside* an effect, move them directly *into* that effect:**
12151216+```jsx {4-12}
1217function SearchResults() {
1218 // ...
1219 useEffect(() => {
···12391240If 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:
12411242+```jsx {6,15}
1243function SearchResults() {
1244 const [query, setQuery] = useState('react');
1245···13021303On 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:
13041305+```jsx {2-5}
1306function SearchResults() {
1307 // 🔴 Re-triggers all effects on every render
1308 function getFetchUrl(query) {
···13291330**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:**
13311332+```jsx {1-4}
1333// ✅ Not affected by the data flow
1334function getFetchUrl(query) {
1335 return 'https://hn.algolia.com/api/v1/search?query=' + query;
···1355Alternatively, you can wrap it into the [`useCallback` Hook](https://reactjs.org/docs/hooks-reference.html#usecallback):
135613571358+```jsx {2-5}
1359function SearchResults() {
1360 // ✅ Preserves identity when its own deps are the same
1361 const getFetchUrl = useCallback((query) => {
···13821383We'll immediately see that it's missing a `query` dependency:
13841385+```jsx {5}
1386function SearchResults() {
1387 const [query, setQuery] = useState('react');
1388 const getFetchUrl = useCallback(() => { // No query argument
···13941395If I fix my `useCallback` deps to include `query`, any effect with `getFetchUrl` in deps will re-run whenever the `query` changes:
13961397+```jsx {4-7}
1398function SearchResults() {
1399 const [query, setQuery] = useState('react');
1400···14161417This is just a consequence of embracing the data flow and the synchronization mindset. **The same solution works for function props passed from parents:**
14181419+```jsx {4-8}
1420function Parent() {
1421 const [query, setQuery] = useState('react');
1422···14461447Interestingly, this pattern is broken with classes in a way that really shows the difference between the effect and lifecycle paradigms. Consider this translation:
14481449+```jsx {5-8,18-20}
1450class Parent extends Component {
1451 state = {
1452 query: 'react'
···14751476You 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`:**
14771478+```jsx {8-13}
1479class Child extends Component {
1480 state = {
1481 data: null
···15151516The 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:
15171518+```jsx {10,22-24}
1519class Parent extends Component {
1520 state = {
1521 query: 'react'
···15911592As 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:
15931594+```jsx {8-12}
1595class Article extends Component {
1596 state = {
1597 article: null
···16221623Alternatively, the easiest stopgap approach is to track it with a boolean:
16241625+```jsx {5,9,16-18}
1626function Article({ id }) {
1627 const [article, setArticle] = useState(null);
1628
···3536Let’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:
3738-```jsx{4,19}
39function getName(user) {
40 let name = user.name;
41 if (name === null) {
···7071This 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`:
7273-```jsx{4,19-21}
74function getName(user) {
75 let name = user.name;
76 if (name === null) {
···103104Instead 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:
105106-```jsx{4}
107function getName(user) {
108 let name = user.name;
109 if (name === null) {
···115116When 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:
117118-```jsx{3}
119try {
120 makeFriends(arya, gendry);
121} handle (effect) {
···127128This 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`:
129130-```jsx{5}
131try {
132 makeFriends(arya, gendry);
133} handle (effect) {
···139140This 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**. 🤯
141142-```jsx{4,6,16,18}
143function getName(user) {
144 let name = user.name;
145 if (name === null) {
···194195For a moment, let’s forget about `async / await` and get back to our example:
196197-```jsx{4,19-21}
198function getName(user) {
199 let name = user.name;
200 if (name === null) {
···223224It turns out, we can call `resume with` asynchronously from our effect handler without making any changes to `getName` or `makeFriends`:
225226-```jsx{19-23}
227function getName(user) {
228 let name = user.name;
229 if (name === null) {
···264265They let you write code that focuses on *what* you’re doing:
266267-```jsx{2,3,5,7,12}
268function enumerateFiles(dir) {
269 const contents = perform OpenDirectory(dir);
270 perform Log('Enumerating files in ', dir);
···282283And later wrap it with something that specifies *how*:
284285-```jsx{6-7,9-11,13-14}
286let files = [];
287try {
288 enumerateFiles('C:\\');
···323324Effect 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:
325326-```jsx{19-23}
327import { withFakeFileSystem } from 'fake-fs';
328329function withLogSnapshot(fn) {
···3536Let’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:
3738+```jsx {4,19}
39function getName(user) {
40 let name = user.name;
41 if (name === null) {
···7071This 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`:
7273+```jsx {4,19-21}
74function getName(user) {
75 let name = user.name;
76 if (name === null) {
···103104Instead 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:
105106+```jsx {4}
107function getName(user) {
108 let name = user.name;
109 if (name === null) {
···115116When 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:
117118+```jsx {3}
119try {
120 makeFriends(arya, gendry);
121} handle (effect) {
···127128This 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`:
129130+```jsx {5}
131try {
132 makeFriends(arya, gendry);
133} handle (effect) {
···139140This 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**. 🤯
141142+```jsx {4,6,16,18}
143function getName(user) {
144 let name = user.name;
145 if (name === null) {
···194195For a moment, let’s forget about `async / await` and get back to our example:
196197+```jsx {4,19-21}
198function getName(user) {
199 let name = user.name;
200 if (name === null) {
···223224It turns out, we can call `resume with` asynchronously from our effect handler without making any changes to `getName` or `makeFriends`:
225226+```jsx {19-23}
227function getName(user) {
228 let name = user.name;
229 if (name === null) {
···264265They let you write code that focuses on *what* you’re doing:
266267+```jsx {2,3,5,7,12}
268function enumerateFiles(dir) {
269 const contents = perform OpenDirectory(dir);
270 perform Log('Enumerating files in ', dir);
···282283And later wrap it with something that specifies *how*:
284285+```jsx {6-7,9-11,13-14}
286let files = [];
287try {
288 enumerateFiles('C:\\');
···323324Effect 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:
325326+```jsx {19-23}
327import { withFakeFileSystem } from 'fake-fs';
328329function withLogSnapshot(fn) {
+4-4
public/before-you-memo/index.md
···5354If you look at the rendering code closer, you'll notice only a part of the returned tree actually cares about the current `color`:
5556-```jsx{2,5-6}
57export default function App() {
58 let [color, setColor] = useState('red');
59 return (
···6869So let's extract that part into a `Form` component and move state _down_ into it:
7071-```jsx{4,11,14,15}
72export default function App() {
73 return (
74 <>
···9798The 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>`:
99100-```jsx{2,4}
101export default function App() {
102 let [color, setColor] = useState('red');
103 return (
···126127The answer is remarkably plain:
128129-```jsx{4,5,10,15}
130export default function App() {
131 return (
132 <ColorPicker>
···5354If you look at the rendering code closer, you'll notice only a part of the returned tree actually cares about the current `color`:
5556+```jsx {2,5-6}
57export default function App() {
58 let [color, setColor] = useState('red');
59 return (
···6869So let's extract that part into a `Form` component and move state _down_ into it:
7071+```jsx {4,11,14,15}
72export default function App() {
73 return (
74 <>
···9798The 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>`:
99100+```jsx {2,4}
101export default function App() {
102 let [color, setColor] = useState('red');
103 return (
···126127The answer is remarkably plain:
128129+```jsx {4,5,10,15}
130export default function App() {
131 return (
132 <ColorPicker>
···112113Let’s look closely at the `showMessage` method in our class:
114115-```jsx{3}
116class ProfilePage extends React.Component {
117 showMessage = () => {
118 alert('Followed ' + this.props.user);
···137138One 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:
139140-```jsx{2,7}
141class ProfilePage extends React.Component {
142 showMessage = (user) => {
143 alert('Followed ' + user);
···162163Perhaps, we could *bind* the methods in the constructor?
164165-```jsx{4-5}
166class ProfilePage extends React.Component {
167 constructor(props) {
168 super(props);
···190191This means that if you close over props or state from a particular render, you can always count on them staying exactly the same:
192193-```jsx{3,4,9}
194class ProfilePage extends React.Component {
195 render() {
196 // Capture the props!
···246247It’s a bit more obvious if you destructure `props` in the function definition:
248249-```jsx{1,3}
250function ProfilePage({ user }) {
251 const showMessage = () => {
252 alert('Followed ' + user);
···329330By 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:
331332-```jsx{3,6,15}
333function MessageThread() {
334 const [message, setMessage] = useState('');
335 const latestMessage = useRef('');
···354355Generally, 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:
356357-```jsx{4-8,11}
358function MessageThread() {
359 const [message, setMessage] = useState('');
360
···112113Let’s look closely at the `showMessage` method in our class:
114115+```jsx {3}
116class ProfilePage extends React.Component {
117 showMessage = () => {
118 alert('Followed ' + this.props.user);
···137138One 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:
139140+```jsx {2,7}
141class ProfilePage extends React.Component {
142 showMessage = (user) => {
143 alert('Followed ' + user);
···162163Perhaps, we could *bind* the methods in the constructor?
164165+```jsx {4-5}
166class ProfilePage extends React.Component {
167 constructor(props) {
168 super(props);
···190191This means that if you close over props or state from a particular render, you can always count on them staying exactly the same:
192193+```jsx {3,4,9}
194class ProfilePage extends React.Component {
195 render() {
196 // Capture the props!
···246247It’s a bit more obvious if you destructure `props` in the function definition:
248249+```jsx {1,3}
250function ProfilePage({ user }) {
251 const showMessage = () => {
252 alert('Followed ' + user);
···329330By 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:
331332+```jsx {3,6,15}
333function MessageThread() {
334 const [message, setMessage] = useState('');
335 const latestMessage = useRef('');
···354355Generally, 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:
356357+```jsx {4-8,11}
358function MessageThread() {
359 const [message, setMessage] = useState('');
360
···7778First, 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:
7980-```jsx{5}
81// If Greeting is a function
82const result = Greeting(props); // <p>Hello</p>
83···116117The `new` operator also makes anything we put on `Person.prototype` available on the `fred` object:
118119-```jsx{4-6,9}
120function Person(name) {
121 this.name = name;
122}
···244245This 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:
246247-```jsx{2,6,7}
248class Friends extends React.Component {
249 render() {
250 const friends = this.props.friends;
···297298However, 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:
299300-```jsx{1-2,7-8,17-18}
301// Created lazily
302var zeroVector = null;
303···371372What’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!**
373374-```jsx{8}
375function Person(name) {
376 this.name = name;
377}
···409410With 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`:
411412-```jsx{1,9,13}
413class Greeting extends React.Component {
414 render() {
415 return <p>Hello</p>;
···447448Since 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:
449450-```jsx{3,4}
451// `__proto__` chain
452new Greeting()
453 → Greeting.prototype // 🕵️ We start here
···7778First, 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:
7980+```jsx {5}
81// If Greeting is a function
82const result = Greeting(props); // <p>Hello</p>
83···116117The `new` operator also makes anything we put on `Person.prototype` available on the `fred` object:
118119+```jsx {4-6,9}
120function Person(name) {
121 this.name = name;
122}
···244245This 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:
246247+```jsx {2,6,7}
248class Friends extends React.Component {
249 render() {
250 const friends = this.props.friends;
···297298However, 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:
299300+```jsx {1-2,7-8,17-18}
301// Created lazily
302var zeroVector = null;
303···371372What’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!**
373374+```jsx {8}
375function Person(name) {
376 this.name = name;
377}
···409410With 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`:
411412+```jsx {1,9,13}
413class Greeting extends React.Component {
414 render() {
415 return <p>Hello</p>;
···447448Since 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:
449450+```jsx {3,4}
451// `__proto__` chain
452new Greeting()
453 → Greeting.prototype // 🕵️ We start here
+3-3
public/how-does-setstate-know-what-to-do/index.md
···78When you call `setState` in a component, what do you think happens?
910-```jsx{11}
11import React from 'react';
12import ReactDOM from 'react-dom';
13···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:
113114115-```jsx{4,9,14}
116// Inside React DOM
117const inst = new YourComponent();
118inst.props = props;
···172173And individual renderers set the dispatcher before rendering your component:
174175-```jsx{3,8-9}
176// In React DOM
177const prevDispatcher = React.__currentDispatcher;
178React.__currentDispatcher = ReactDOMDispatcher;
···78When you call `setState` in a component, what do you think happens?
910+```jsx {11}
11import React from 'react';
12import ReactDOM from 'react-dom';
13···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:
113114115+```jsx {4,9,14}
116// Inside React DOM
117const inst = new YourComponent();
118inst.props = props;
···172173And individual renderers set the dispatcher before rendering your component:
174175+```jsx {3,8-9}
176// In React DOM
177const prevDispatcher = React.__currentDispatcher;
178React.__currentDispatcher = ReactDOMDispatcher;
···3031Without further ado, here’s a counter that increments every second:
3233-```jsx{6-9}
34import React, { useState, useEffect, useRef } from 'react';
3536function Counter() {
···128129So how would you do this with `setInterval` in a class? I ended up with this:
130131-```jsx{7-26}
132class Counter extends React.Component {
133 state = {
134 count: 0,
···179180<font size="50">🥁🥁🥁</font>
181182-```jsx{5-8}
183function Counter() {
184 let [count, setCount] = useState(0);
185 let [delay, setDelay] = useState(1000);
···208209Unlike the class version, there is no complexity gap for “upgrading” the `useInterval` Hook example to have a dynamically adjusted delay:
210211-```jsx{4,9}
212 // Constant delay
213 useInterval(() => {
214 setCount(count + 1);
···226227What if I want to temporarily *pause* my interval? I can do this with state too:
228229-```jsx{6}
230 const [delay, setDelay] = useState(1000);
231 const [isRunning, setIsRunning] = useState(true);
232···260261Now 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:
262263-```jsx{4-9}
264function Counter() {
265 let [count, setCount] = useState(0);
266···304305You 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:
306307-```jsx{3}
308useEffect(() => {
309 document.title = `You clicked ${count} times`;
310}, [count]);
···316317In 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:
318319-```jsx{9}
320function Counter() {
321 let [count, setCount] = useState(0);
322···364365Hooks let us apply the same declarative approach to effects:
366367-```jsx{4}
368 // Describes every interval state
369 useInterval(() => {
370 setCount(count + 1);
···420421`useRef()` returns a plain object with a mutable `current` property that’s shared between renders. We can save the *latest* interval callback into it:
422423-```jsx{8}
424 function callback() {
425 // Can read fresh props, state, etc.
426 setCount(count + 1);
···434435And then we can read and call it from inside our interval:
436437-```jsx{3,8}
438 useEffect(() => {
439 function tick() {
440 savedCallback.current();
···449450Here’s a complete working solution:
451452-```jsx{10,15}
453function Counter() {
454 const [count, setCount] = useState(0);
455 const savedCallback = useRef();
···487488Ideally, I just want to write this:
489490-```jsx{4-6}
491function Counter() {
492 const [count, setCount] = useState(0);
493···534535 Now that the `delay` can change between renders, I need to declare it in the dependencies of my interval effect:
536537-```jsx{8}
538 useEffect(() => {
539 function tick() {
540 savedCallback.current();
···586587Say we want to be able to pause our interval by passing `null` as the `delay`:
588589-```jsx{6}
590 const [delay, setDelay] = useState(1000);
591 const [isRunning, setIsRunning] = useState(true);
592···597598How do we implement this? The answer is: by not setting up an interval.
599600-```jsx{6}
601 useEffect(() => {
602 function tick() {
603 savedCallback.current();
···622623
624625-```jsx{10-15}
626function Counter() {
627 const [delay, setDelay] = useState(1000);
628 const [count, setCount] = useState(0);
···3031Without further ado, here’s a counter that increments every second:
3233+```jsx {6-9}
34import React, { useState, useEffect, useRef } from 'react';
3536function Counter() {
···128129So how would you do this with `setInterval` in a class? I ended up with this:
130131+```jsx {7-26}
132class Counter extends React.Component {
133 state = {
134 count: 0,
···179180<font size="50">🥁🥁🥁</font>
181182+```jsx {5-8}
183function Counter() {
184 let [count, setCount] = useState(0);
185 let [delay, setDelay] = useState(1000);
···208209Unlike the class version, there is no complexity gap for “upgrading” the `useInterval` Hook example to have a dynamically adjusted delay:
210211+```jsx {4,9}
212 // Constant delay
213 useInterval(() => {
214 setCount(count + 1);
···226227What if I want to temporarily *pause* my interval? I can do this with state too:
228229+```jsx {6}
230 const [delay, setDelay] = useState(1000);
231 const [isRunning, setIsRunning] = useState(true);
232···260261Now 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:
262263+```jsx {4-9}
264function Counter() {
265 let [count, setCount] = useState(0);
266···304305You 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:
306307+```jsx {3}
308useEffect(() => {
309 document.title = `You clicked ${count} times`;
310}, [count]);
···316317In 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:
318319+```jsx {9}
320function Counter() {
321 let [count, setCount] = useState(0);
322···364365Hooks let us apply the same declarative approach to effects:
366367+```jsx {4}
368 // Describes every interval state
369 useInterval(() => {
370 setCount(count + 1);
···420421`useRef()` returns a plain object with a mutable `current` property that’s shared between renders. We can save the *latest* interval callback into it:
422423+```jsx {8}
424 function callback() {
425 // Can read fresh props, state, etc.
426 setCount(count + 1);
···434435And then we can read and call it from inside our interval:
436437+```jsx {3,8}
438 useEffect(() => {
439 function tick() {
440 savedCallback.current();
···449450Here’s a complete working solution:
451452+```jsx {10,15}
453function Counter() {
454 const [count, setCount] = useState(0);
455 const savedCallback = useRef();
···487488Ideally, I just want to write this:
489490+```jsx {4-6}
491function Counter() {
492 const [count, setCount] = useState(0);
493···534535 Now that the `delay` can change between renders, I need to declare it in the dependencies of my interval effect:
536537+```jsx {8}
538 useEffect(() => {
539 function tick() {
540 savedCallback.current();
···586587Say we want to be able to pause our interval by passing `null` as the `delay`:
588589+```jsx {6}
590 const [delay, setDelay] = useState(1000);
591 const [isRunning, setIsRunning] = useState(true);
592···597598How do we implement this? The answer is: by not setting up an interval.
599600+```jsx {6}
601 useEffect(() => {
602 function tick() {
603 savedCallback.current();
···622623
624625+```jsx {10-15}
626function Counter() {
627 const [delay, setDelay] = useState(1000);
628 const [count, setCount] = useState(0);
+1-1
public/my-wishlist-for-hot-reloading/index.md
···5960For 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:
6162-```jsx{4}
63// Reassigns the latest version
64window.latest_Button = function(props) {
65 // Your actual code is moved here by a plugin
···5960For 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:
6162+```jsx {4}
63// Reassigns the latest version
64window.latest_Button = function(props) {
65 // Your actual code is moved here by a plugin
+23-23
public/react-as-a-ui-runtime/index.md
···134135React 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:
136137-```jsx{3,4}
138// Somewhere in the ReactDOM renderer (simplified)
139function createHostInstance(reactElement) {
140 let domNode = document.createElement(reactElement.type);
···145146In our example, effectively React will do this:
147148-```jsx{1,2}
149let domNode = document.createElement('button');
150domNode.className = 'blue';
151···158159What happens if we call `ReactDOM.render()` twice with the same container?
160161-```jsx{2,11}
162ReactDOM.render(
163 <button className="blue" />,
164 document.getElementById('container')
···208209Here is an example with comments showing roughly what React does:
210211-```jsx{9,10,16,26,27}
212// let domNode = document.createElement('button');
213// domNode.className = 'blue';
214// domContainer.appendChild(domNode);
···250251Say we want to first show only an input, but later render a message before it:
252253-```jsx{12}
254// First render
255ReactDOM.render(
256 <dialog>
···277278So effectively the update code executed by React would be like:
279280-```jsx{1,2,8,9}
281let oldInputNode = dialogNode.firstChild;
282dialogNode.removeChild(oldInputNode);
283···312313This 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:
314315-```jsx{12-15}
316function Form({ showMessage }) {
317 let message = null;
318 if (showMessage) {
···392393**This is why React nags you to specify a special property called `key` every time you include an array of elements in your output:**
394395-```jsx{5}
396function ShoppingList({ list }) {
397 return (
398 <form>
···454455However, *local mutation* is absolutely fine:
456457-```jsx{2,5}
458function FriendList({ friends }) {
459 let items = [];
460 for (let i = 0; i < friends.length; i++) {
···602603Consider this component putting `<Comments>` inside a `<Page>`:
604605-```jsx{11}
606function Story({ currentUser }) {
607 // return {
608 // type: Page,
···621622The `Page` component can render the children given to it inside some `Layout`:
623624-```jsx{4}
625function Page({ user, children }) {
626 return (
627 <Layout>
···635636But what if it has an early exit condition?
637638-```jsx{2-4}
639function Page({ user, children }) {
640 if (!user.isLoggedIn) {
641 return <h1>Please log in</h1>;
···650651If we called `Comments()` as a function, it would execute immediately regardless of whether `Page` wants to render them or not:
652653-```jsx{4,8}
654// {
655// type: Page,
656// props: {
···664665But if we pass a React element, we don’t execute `Comments` ourselves at all:
666667-```jsx{4,8}
668// {
669// type: Page,
670// props: {
···689690We call these features *Hooks*. For example, `useState` is a Hook.
691692-```jsx{2,6,7}
693function Example() {
694 const [count, setCount] = useState(0);
695···723724When 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:
725726-```jsx{5}
727function Row({ item }) {
728 // ...
729}
···754755Several components may want to update state in response to the same event. This example is contrived but it illustrates a common pattern:
756757-```jsx{4,14}
758function Parent() {
759 let [count, setCount] = useState(0);
760 return (
···779780If React immediately re-rendered components in response to `setState` calls, we’d end up rendering the child twice:
781782-```jsx{4,8}
783*** Entering React's browser click event handler ***
784Child (onClick)
785 - setState
···916917In React, this is done by declaring an effect:
918919-```jsx{4-6}
920function Example() {
921 const [count, setCount] = useState(0);
922···952953Sometimes, 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:
954955-```jsx{3}
956 useEffect(() => {
957 document.title = `You clicked ${count} times`;
958 }, [count]);
···981982To solve this, make sure that if you specify the dependency array, it includes **all** things that can change, including the functions:
983984-```jsx{4}
985 useEffect(() => {
986 DataSource.addSubscription(handleChange);
987 return () => DataSource.removeSubscription(handleChange);
···996997Since Hooks like `useState` and `useEffect` are function calls, we can compose them into our own Hooks:
998999-```jsx{2,8}
1000function MyResponsiveComponent() {
1001 const width = useWindowWidth(); // Our custom Hook
1002 return (
···10271028If `use` *were* a syntax, it would make sense for it to be at the top level:
10291030-```jsx{3}
1031// 😉 Note: not a real syntax
1032component Example(props) {
1033 const [count, setCount] = use State(0);
···134135React 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:
136137+```jsx {3,4}
138// Somewhere in the ReactDOM renderer (simplified)
139function createHostInstance(reactElement) {
140 let domNode = document.createElement(reactElement.type);
···145146In our example, effectively React will do this:
147148+```jsx {1,2}
149let domNode = document.createElement('button');
150domNode.className = 'blue';
151···158159What happens if we call `ReactDOM.render()` twice with the same container?
160161+```jsx {2,11}
162ReactDOM.render(
163 <button className="blue" />,
164 document.getElementById('container')
···208209Here is an example with comments showing roughly what React does:
210211+```jsx {9,10,16,26,27}
212// let domNode = document.createElement('button');
213// domNode.className = 'blue';
214// domContainer.appendChild(domNode);
···250251Say we want to first show only an input, but later render a message before it:
252253+```jsx {12}
254// First render
255ReactDOM.render(
256 <dialog>
···277278So effectively the update code executed by React would be like:
279280+```jsx {1,2,8,9}
281let oldInputNode = dialogNode.firstChild;
282dialogNode.removeChild(oldInputNode);
283···312313This 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:
314315+```jsx {12-15}
316function Form({ showMessage }) {
317 let message = null;
318 if (showMessage) {
···392393**This is why React nags you to specify a special property called `key` every time you include an array of elements in your output:**
394395+```jsx {5}
396function ShoppingList({ list }) {
397 return (
398 <form>
···454455However, *local mutation* is absolutely fine:
456457+```jsx {2,5}
458function FriendList({ friends }) {
459 let items = [];
460 for (let i = 0; i < friends.length; i++) {
···602603Consider this component putting `<Comments>` inside a `<Page>`:
604605+```jsx {11}
606function Story({ currentUser }) {
607 // return {
608 // type: Page,
···621622The `Page` component can render the children given to it inside some `Layout`:
623624+```jsx {4}
625function Page({ user, children }) {
626 return (
627 <Layout>
···635636But what if it has an early exit condition?
637638+```jsx {2-4}
639function Page({ user, children }) {
640 if (!user.isLoggedIn) {
641 return <h1>Please log in</h1>;
···650651If we called `Comments()` as a function, it would execute immediately regardless of whether `Page` wants to render them or not:
652653+```jsx {4,8}
654// {
655// type: Page,
656// props: {
···664665But if we pass a React element, we don’t execute `Comments` ourselves at all:
666667+```jsx {4,8}
668// {
669// type: Page,
670// props: {
···689690We call these features *Hooks*. For example, `useState` is a Hook.
691692+```jsx {2,6,7}
693function Example() {
694 const [count, setCount] = useState(0);
695···723724When 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:
725726+```jsx {5}
727function Row({ item }) {
728 // ...
729}
···754755Several components may want to update state in response to the same event. This example is contrived but it illustrates a common pattern:
756757+```jsx {4,14}
758function Parent() {
759 let [count, setCount] = useState(0);
760 return (
···779780If React immediately re-rendered components in response to `setState` calls, we’d end up rendering the child twice:
781782+```jsx {4,8}
783*** Entering React's browser click event handler ***
784Child (onClick)
785 - setState
···916917In React, this is done by declaring an effect:
918919+```jsx {4-6}
920function Example() {
921 const [count, setCount] = useState(0);
922···952953Sometimes, 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:
954955+```jsx {3}
956 useEffect(() => {
957 document.title = `You clicked ${count} times`;
958 }, [count]);
···981982To solve this, make sure that if you specify the dependency array, it includes **all** things that can change, including the functions:
983984+```jsx {4}
985 useEffect(() => {
986 DataSource.addSubscription(handleChange);
987 return () => DataSource.removeSubscription(handleChange);
···996997Since Hooks like `useState` and `useEffect` are function calls, we can compose them into our own Hooks:
998999+```jsx {2,8}
1000function MyResponsiveComponent() {
1001 const width = useWindowWidth(); // Our custom Hook
1002 return (
···10271028If `use` *were* a syntax, it would make sense for it to be at the top level:
10291030+```jsx {3}
1031// 😉 Note: not a real syntax
1032component Example(props) {
1033 const [count, setCount] = use State(0);
+1-1
public/the-bug-o-notation/index.md
···116117This code might not look too different. It’s even a bit more verbose. But it is *dramatically* simpler to debug because of this line:
118119-```jsx{3}
120function setState(nextState) {
121 // Clear all existing children
122 formStatus.innerHTML = '';
···116117This code might not look too different. It’s even a bit more verbose. But it is *dramatically* simpler to debug because of this line:
118119+```jsx {3}
120function setState(nextState) {
121 // Clear all existing children
122 formStatus.innerHTML = '';
+12-12
public/why-do-hooks-rely-on-call-order/index.md
···3536There 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:
3738-```jsx{2,3,4}
39function Form() {
40 const [name, setName] = useState('Mary'); // State variable 1
41 const [surname, setSurname] = useState('Poppins'); // State variable 2
···103104But 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:
105106-```jsx{6-7}
107function Form() {
108 // Declare some state variables directly in component body
109 const [name, setName] = useState('Mary');
···174175This proposal seems to work for extracting the `useWindowWidth()` Hook:
176177-```jsx{4,11-17}
178// ⚠️ This is NOT the React Hooks API
179function Form() {
180 // ...
···196197But if we attempt to extract input handling, it would fail:
198199-```jsx{4,5,19-29}
200// ⚠️ This is NOT the React Hooks API
201function Form() {
202 // ...
···251252Two custom Hooks like `useWindowWidth()` and `useNetworkStatus()` might want to use the same custom Hook like `useSubscription()` under the hood:
253254-```jsx{12,23-27,32-42}
255function StatusMessage() {
256 const width = useWindowWidth();
257 const isOnline = useNetworkStatus();
···330331One 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:
332333-```jsx{5,6}
334/*******************
335 * useFormInput.js *
336 ******************/
···354355Additionally, 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:
356357-```jsx{2,3,7,8}
358// ⚠️ This is NOT the React Hooks API
359const useNameFormInput = createUseFormInput();
360const useSurnameFormInput = createUseFormInput();
···386387The idea is that we could *compose* keys every time we write a custom Hook. Something like this:
388389-```jsx{4,5,16,17}
390// ⚠️ This is NOT the React Hooks API
391function Form() {
392 // ...
···423424What does this code mean exactly?
425426-```jsx{3,4}
427// ⚠️ This is NOT the React Hooks API
428function Counter(props) {
429 if (props.isActive) {
···442443If conditional state gets preserved, what about an effect?
444445-```jsx{5-8}
446// ⚠️ This is NOT the React Hooks API
447function Counter(props) {
448 if (props.isActive) {
···487488Here is a hypothetical example of a message recipient picker that shows whether the currently chosen friend is online:
489490-```jsx{8,9}
491const friendList = [
492 { id: 1, name: 'Phoebe' },
493 { id: 2, name: 'Rachel' },
···532533This works because we can pass the return value of the `useState()` Hook to the `useFriendStatus()` Hook:
534535-```jsx{2}
536 const [recipientID, setRecipientID] = useState(1);
537 const isRecipientOnline = useFriendStatus(recipientID);
538```
···3536There 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:
3738+```jsx {2,3,4}
39function Form() {
40 const [name, setName] = useState('Mary'); // State variable 1
41 const [surname, setSurname] = useState('Poppins'); // State variable 2
···103104But 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:
105106+```jsx {6-7}
107function Form() {
108 // Declare some state variables directly in component body
109 const [name, setName] = useState('Mary');
···174175This proposal seems to work for extracting the `useWindowWidth()` Hook:
176177+```jsx {4,11-17}
178// ⚠️ This is NOT the React Hooks API
179function Form() {
180 // ...
···196197But if we attempt to extract input handling, it would fail:
198199+```jsx {4,5,19-29}
200// ⚠️ This is NOT the React Hooks API
201function Form() {
202 // ...
···251252Two custom Hooks like `useWindowWidth()` and `useNetworkStatus()` might want to use the same custom Hook like `useSubscription()` under the hood:
253254+```jsx {12,23-27,32-42}
255function StatusMessage() {
256 const width = useWindowWidth();
257 const isOnline = useNetworkStatus();
···330331One 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:
332333+```jsx {5,6}
334/*******************
335 * useFormInput.js *
336 ******************/
···354355Additionally, 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:
356357+```jsx {2,3,7,8}
358// ⚠️ This is NOT the React Hooks API
359const useNameFormInput = createUseFormInput();
360const useSurnameFormInput = createUseFormInput();
···386387The idea is that we could *compose* keys every time we write a custom Hook. Something like this:
388389+```jsx {4,5,16,17}
390// ⚠️ This is NOT the React Hooks API
391function Form() {
392 // ...
···423424What does this code mean exactly?
425426+```jsx {3,4}
427// ⚠️ This is NOT the React Hooks API
428function Counter(props) {
429 if (props.isActive) {
···442443If conditional state gets preserved, what about an effect?
444445+```jsx {5-8}
446// ⚠️ This is NOT the React Hooks API
447function Counter(props) {
448 if (props.isActive) {
···487488Here is a hypothetical example of a message recipient picker that shows whether the currently chosen friend is online:
489490+```jsx {8,9}
491const friendList = [
492 { id: 1, name: 'Phoebe' },
493 { id: 2, name: 'Rachel' },
···532533This works because we can pass the return value of the `useState()` Hook to the `useFriendStatus()` Hook:
534535+```jsx {2}
536 const [recipientID, setRecipientID] = useState(1);
537 const isRecipientOnline = useFriendStatus(recipientID);
538```
···2324And 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.
2526-```jsx{9}
27{
28 type: 'marquee',
29 props: {
···105106However, **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:
107108-```jsx{2-10,15}
109// Server could have a hole that lets user store JSON
110let expectedTextButGotJSON = {
111 type: 'div',
···128129The fix in React 0.14 was to [tag every React element with a Symbol](https://github.com/facebook/react/pull/4832):
130131-```jsx{9}
132{
133 type: 'marquee',
134 props: {
···2324And 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.
2526+```jsx {9}
27{
28 type: 'marquee',
29 props: {
···105106However, **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:
107108+```jsx {2-10,15}
109// Server could have a hole that lets user store JSON
110let expectedTextButGotJSON = {
111 type: 'div',
···128129The fix in React 0.14 was to [tag every React element with a Symbol](https://github.com/facebook/react/pull/4832):
130131+```jsx {9}
132{
133 type: 'marquee',
134 props: {
+3-3
public/why-do-we-write-super-props/index.md
···1516I wrote `super(props)` more times in my life than I’d like to know:
1718-```jsx{3}
19class Checkbox extends React.Component {
20 constructor(props) {
21 super(props);
···3839But let’s get back to this example using only ES2015 features:
4041-```jsx{3}
42class Checkbox extends React.Component {
43 constructor(props) {
44 super(props);
···145146**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:
147148-```jsx{14}
149// Inside React
150class Component {
151 constructor(props) {
···1516I wrote `super(props)` more times in my life than I’d like to know:
1718+```jsx {3}
19class Checkbox extends React.Component {
20 constructor(props) {
21 super(props);
···3839But let’s get back to this example using only ES2015 features:
4041+```jsx {3}
42class Checkbox extends React.Component {
43 constructor(props) {
44 super(props);
···145146**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:
147148+```jsx {14}
149// Inside React
150class Component {
151 constructor(props) {
+4-4
public/why-isnt-x-a-hook/index.md
···6162Hooks are useful because you can pass values *between* Hooks:
6364-```jsx{4,12,14}
65function useWindowWidth() {
66 const [width, setWidth] = useState(window.innerWidth);
67 // ...
···108109`React.memo()` takes a component and returns a component:
110111-```jsx{4}
112function Button(props) {
113 // ...
114}
···138139Let’s say we try to put `useBailout()` in two custom Hooks:
140141-```jsx{4,5,19,20}
142function useFriendStatus(friendID) {
143 const [isOnline, setIsOnline] = useState(null);
144···173Now what happens if you use them both in the same component?
174175176-```jsx{2,3}
177function ChatThread({ friendID, isTyping }) {
178 const width = useWindowWidth();
179 const isOnline = useFriendStatus(friendID);
···6162Hooks are useful because you can pass values *between* Hooks:
6364+```jsx {4,12,14}
65function useWindowWidth() {
66 const [width, setWidth] = useState(window.innerWidth);
67 // ...
···108109`React.memo()` takes a component and returns a component:
110111+```jsx {4}
112function Button(props) {
113 // ...
114}
···138139Let’s say we try to put `useBailout()` in two custom Hooks:
140141+```jsx {4,5,19,20}
142function useFriendStatus(friendID) {
143 const [isOnline, setIsOnline] = useState(null);
144···173Now what happens if you use them both in the same component?
174175176+```jsx {2,3}
177function ChatThread({ friendID, isTyping }) {
178 const width = useWindowWidth();
179 const isOnline = useFriendStatus(friendID);
+24-24
public/writing-resilient-components/index.md
···9192However, a common mistake when learning React is to copy props into state:
9394-```jsx{3,6}
95class Button extends React.Component {
96 state = {
97 color: this.props.color
···133134Computed 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:
135136-```jsx{3,9}
137class Button extends React.Component {
138 state = {
139 textColor: slowlyCalculateTextColor(this.props.color)
···153154This 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`:
155156-```jsx{1,3}
157class Button extends React.PureComponent {
158 render() {
159 const textColor = slowlyCalculateTextColor(this.props.color);
···173174However, 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`:
175176-```jsx{5-12}
177class Button extends React.Component {
178 state = {
179 textColor: slowlyCalculateTextColor(this.props.color)
···207208With 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:
209210-```jsx{2-5}
211function Button({ color, children }) {
212 const textColor = useMemo(
213 () => slowlyCalculateTextColor(color),
···235236Consider this React component:
237238-```jsx{5-7}
239class SearchResults extends React.Component {
240 state = {
241 data: null
···258259A 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:
260261-```jsx{2}
262 getFetchUrl() {
263 return 'http://myapi/results?query' + this.props.query;
264 }
···275* Make sure that whenever those props change, we re-run the side effect.
276 - We can do this by adding the `componentDidUpdate` method.
277278-```jsx{8-12,18}
279class SearchResults extends React.Component {
280 state = {
281 data: null
···305306However, 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`:
307308-```jsx{4,21}
309class SearchResults extends React.Component {
310 state = {
311 data: null,
···350351Let’s fix our component to handle updates to the `currentPage` state:
352353-```jsx{11,24}
354class SearchResults extends React.Component {
355 state = {
356 data: null,
···391392However, 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:
393394-```jsx{13-14,19}
395function SearchResults({ query }) {
396 const [data, setData] = useState(null);
397 const [currentPage, setCurrentPage] = useState(0);
···442443**However, if you try to “optimize” a component by writing your own comparison, you may mistakenly forget to compare function props:**
444445-```jsx{2-5,7}
446class Button extends React.Component {
447 shouldComponentUpdate(prevProps) {
448 // 🔴 Doesn't compare this.props.onClick
···464465It 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:
466467-```jsx{2-4,9-11}
468class MyForm extends React.Component {
469 handleClick = () => { // ✅ Always the same function
470 // Do something
···484485So 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:
486487-```jsx{6,13-15}
488class MyForm extends React.Component {
489 state = {
490 isEnabled: true
···513514This could get even more confusing if the function identity itself depends on something that could change over time, like `draft.content` in this example:
515516-```jsx{6-7}
517 drafts.map(draft =>
518 <Button
519 color='blue'
···533534I 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:
535536-```jsx{11}
537function Button({ onClick, color, children }) {
538 const textColor = slowlyCalculateTextColor(color);
539 return (
···553554If you insist on a custom comparison, **make sure that you don’t skip functions:**
555556-```jsx{5}
557 shouldComponentUpdate(prevProps) {
558 // ✅ Compares this.props.onClick
559 return (
···586587How can one violate this principle? React doesn’t make it very easy — but you can do it by using the legacy `componentWillReceiveProps` lifecycle method:
588589-```jsx{5-8}
590class TextInput extends React.Component {
591 state = {
592 value: ''
···659660To stress-test your component, you can temporarily add this code to its parent:
661662-```jsx{2}
663componentDidMount() {
664 // Don't forget to remove this immediately!
665 setInterval(() => this.forceUpdate(), 100);
···674675This code should work, right?
676677-```jsx{1-2}
678// 🤔 Should prevent unnecessary re-renders... right?
679class TextInput extends React.PureComponent {
680 state = {
···702703However, 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:
704705-```jsx{2}
706<TextInput
707 style={{opacity: someValueFromState}}
708 value={
···727728It’s easy to check for these problems. Just for fun, try to render your app twice:
729730-```jsx{3,4}
731ReactDOM.render(
732 <>
733 <MyApp />
···743744An example of a problematic pattern I’ve written myself a few times is performing global state “cleanup” in `componentWillUnmount`:
745746-```jsx{2-3}
747componentWillUnmount() {
748 // Resets something in Redux store
749 this.props.resetForm();
···752753Of 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:
754755-```jsx{2-3}
756componentDidMount() {
757 // Resets something in Redux store
758 this.props.resetForm();
···9192However, a common mistake when learning React is to copy props into state:
9394+```jsx {3,6}
95class Button extends React.Component {
96 state = {
97 color: this.props.color
···133134Computed 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:
135136+```jsx {3,9}
137class Button extends React.Component {
138 state = {
139 textColor: slowlyCalculateTextColor(this.props.color)
···153154This 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`:
155156+```jsx {1,3}
157class Button extends React.PureComponent {
158 render() {
159 const textColor = slowlyCalculateTextColor(this.props.color);
···173174However, 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`:
175176+```jsx {5-12}
177class Button extends React.Component {
178 state = {
179 textColor: slowlyCalculateTextColor(this.props.color)
···207208With 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:
209210+```jsx {2-5}
211function Button({ color, children }) {
212 const textColor = useMemo(
213 () => slowlyCalculateTextColor(color),
···235236Consider this React component:
237238+```jsx {5-7}
239class SearchResults extends React.Component {
240 state = {
241 data: null
···258259A 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:
260261+```jsx {2}
262 getFetchUrl() {
263 return 'http://myapi/results?query' + this.props.query;
264 }
···275* Make sure that whenever those props change, we re-run the side effect.
276 - We can do this by adding the `componentDidUpdate` method.
277278+```jsx {8-12,18}
279class SearchResults extends React.Component {
280 state = {
281 data: null
···305306However, 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`:
307308+```jsx {4,21}
309class SearchResults extends React.Component {
310 state = {
311 data: null,
···350351Let’s fix our component to handle updates to the `currentPage` state:
352353+```jsx {11,24}
354class SearchResults extends React.Component {
355 state = {
356 data: null,
···391392However, 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:
393394+```jsx {13-14,19}
395function SearchResults({ query }) {
396 const [data, setData] = useState(null);
397 const [currentPage, setCurrentPage] = useState(0);
···442443**However, if you try to “optimize” a component by writing your own comparison, you may mistakenly forget to compare function props:**
444445+```jsx {2-5,7}
446class Button extends React.Component {
447 shouldComponentUpdate(prevProps) {
448 // 🔴 Doesn't compare this.props.onClick
···464465It 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:
466467+```jsx {2-4,9-11}
468class MyForm extends React.Component {
469 handleClick = () => { // ✅ Always the same function
470 // Do something
···484485So 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:
486487+```jsx {6,13-15}
488class MyForm extends React.Component {
489 state = {
490 isEnabled: true
···513514This could get even more confusing if the function identity itself depends on something that could change over time, like `draft.content` in this example:
515516+```jsx {6-7}
517 drafts.map(draft =>
518 <Button
519 color='blue'
···533534I 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:
535536+```jsx {11}
537function Button({ onClick, color, children }) {
538 const textColor = slowlyCalculateTextColor(color);
539 return (
···553554If you insist on a custom comparison, **make sure that you don’t skip functions:**
555556+```jsx {5}
557 shouldComponentUpdate(prevProps) {
558 // ✅ Compares this.props.onClick
559 return (
···586587How can one violate this principle? React doesn’t make it very easy — but you can do it by using the legacy `componentWillReceiveProps` lifecycle method:
588589+```jsx {5-8}
590class TextInput extends React.Component {
591 state = {
592 value: ''
···659660To stress-test your component, you can temporarily add this code to its parent:
661662+```jsx {2}
663componentDidMount() {
664 // Don't forget to remove this immediately!
665 setInterval(() => this.forceUpdate(), 100);
···674675This code should work, right?
676677+```jsx {1-2}
678// 🤔 Should prevent unnecessary re-renders... right?
679class TextInput extends React.PureComponent {
680 state = {
···702703However, 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:
704705+```jsx {2}
706<TextInput
707 style={{opacity: someValueFromState}}
708 value={
···727728It’s easy to check for these problems. Just for fun, try to render your app twice:
729730+```jsx {3,4}
731ReactDOM.render(
732 <>
733 <MyApp />
···743744An example of a problematic pattern I’ve written myself a few times is performing global state “cleanup” in `componentWillUnmount`:
745746+```jsx {2-3}
747componentWillUnmount() {
748 // Resets something in Redux store
749 this.props.resetForm();
···752753Of 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:
754755+```jsx {2-3}
756componentDidMount() {
757 // Resets something in Redux store
758 this.props.resetForm();