diff --git a/app/[slug]/page.js b/app/[slug]/page.js index 2ed352f..ac78526 100644 --- a/app/[slug]/page.js +++ b/app/[slug]/page.js @@ -18,13 +18,11 @@ export async function generateMetadata({ params }) { export default async function PostPage({ params }) { const file = await readFile("./public/" + params.slug + "/index.md", "utf8"); - let { content, data } = matter(file); - // TODO: change the source instead of this hack. - content = content.replaceAll("```jsx{", "```jsx {"); + const { content, data } = matter(file); const discussUrl = `https://x.com/search?q=${encodeURIComponent( `https://overreacted.io/${params.slug}/`, )}`; - const editUrl = `https://github.com/gaearon/overreacted.io/edit/master/public/${encodeURIComponent( + const editUrl = `https://github.com/gaearon/overreacted.io/edit/main/public/${encodeURIComponent( params.slug, )}/index.md`; return ( diff --git a/public/a-complete-guide-to-useeffect/index.md b/public/a-complete-guide-to-useeffect/index.md index 36ef186..c49076c 100644 --- a/public/a-complete-guide-to-useeffect/index.md +++ b/public/a-complete-guide-to-useeffect/index.md @@ -74,7 +74,7 @@ Before we can talk about effects, we need to talk about rendering. Here’s a counter. Look at the highlighted line closely: -```jsx{6} +```jsx {6} function Counter() { const [count, setCount] = useState(0); @@ -102,7 +102,7 @@ const count = 42; The first time our component renders, the `count` variable we get from `useState()` is `0`. When we call `setCount(1)`, React calls our component again. This time, `count` will be `1`. And so on: -```jsx{3,11,19} +```jsx {3,11,19} // During first render function Counter() { const count = 0; // Returned by useState() @@ -148,7 +148,7 @@ So far so good. What about event handlers? Look at this example. It shows an alert with the `count` after three seconds: -```jsx{4-8,16-18} +```jsx {4-8,16-18} function Counter() { const [count, setCount] = useState(0); @@ -204,7 +204,7 @@ We’ve discussed that the `count` value is constant for every particular call t This is not specific to React — regular functions work in a similar way: -```jsx{2} +```jsx {2} function sayHi(person) { const name = person.name; setTimeout(() => { @@ -226,7 +226,7 @@ In [this example](https://codesandbox.io/s/mm6ww11lk8), the outer `someone` vari This explains how our event handler captures the `count` at the time of the click. If we apply the same substitution principle, each render “sees” its own `count`: -```jsx{3,15,27} +```jsx {3,15,27} // During first render function Counter() { const count = 0; // Returned by useState() @@ -266,7 +266,7 @@ function Counter() { So effectively, each render returns its own “version” of `handleAlertClick`. Each of those versions “remembers” its own `count`: -```jsx{6,10,19,23,32,36} +```jsx {6,10,19,23,32,36} // During first render function Counter() { // ... @@ -319,7 +319,7 @@ This was supposed to be a post about effects but we still haven’t talked about Let’s go back to an example from [the docs](https://reactjs.org/docs/hooks-effect.html): -```jsx{4-6} +```jsx {4-6} function Counter() { const [count, setCount] = useState(0); @@ -350,7 +350,7 @@ We already know that `count` is constant within a particular component render. E Each version “sees” the `count` value from the render that it “belongs” to: -```jsx{5-8,17-20,29-32} +```jsx {5-8,17-20,29-32} // During first render function Counter() { // ... @@ -433,7 +433,7 @@ Now let’s recap what happens after we click: Let’s try a thought experiment. Consider this code: -```jsx{4-8} +```jsx {4-8} function Counter() { const [count, setCount] = useState(0); @@ -493,7 +493,7 @@ At this point it’s important that we call it out explicitly: **every** functio So these two examples are equivalent: -```jsx{4} +```jsx {4} function Example(props) { useEffect(() => { setTimeout(() => { @@ -504,7 +504,7 @@ function Example(props) { } ``` -```jsx{2,5} +```jsx {2,5} function Example(props) { const counter = props.counter; useEffect(() => { @@ -524,7 +524,7 @@ Be aware that when you want to read the *future* props or state from a function Here’s a [version of our counter example](https://codesandbox.io/s/rm7z22qnlp) that replicates the class behavior: -```jsx{3,6-7,9-10} +```jsx {3,6-7,9-10} function Example() { const [count, setCount] = useState(0); const latestCount = useRef(count); @@ -588,7 +588,7 @@ Quoting the previous section: Now the answer is clear! The effect cleanup doesn’t read the “latest” props, whatever that means. It reads props that belong to the render it’s defined in: -```jsx{8-11} +```jsx {8-11} // First render, props are {id: 10} function Example() { // ... @@ -650,7 +650,7 @@ People say: “It’s all about the journey, not the destination”. With React, You should think of effects in a similar way. **`useEffect` lets you _synchronize_ things outside of the React tree according to our props and state.** -```jsx{2-4} +```jsx {2-4} function Greeting({ name }) { useEffect(() => { document.title = 'Hello, ' + name; @@ -709,7 +709,7 @@ domNode.innerText = 'Hello, Yuzhi'; For example, maybe our component re-renders because of a state change: -```jsx{11-13} +```jsx {11-13} function Greeting({ name }) { const [counter, setCounter] = useState(0); @@ -743,7 +743,7 @@ Not really. React can’t guess what the function does without calling it. (The This is why if you want to avoid re-running effects unnecessarily, you can provide a dependency array (also known as “deps”) argument to `useEffect`: -```jsx{3} +```jsx {3} useEffect(() => { document.title = 'Hello, ' + name; }, [name]); // Our deps @@ -796,7 +796,7 @@ But before we jump to solutions, let’s understand the problem better. If deps contain every value used by the effect, React knows when to re-run it: -```jsx{3} +```jsx {3} useEffect(() => { document.title = 'Hello, ' + name; }, [name]); @@ -808,7 +808,7 @@ If deps contain every value used by the effect, React knows when to re-run it: But if we specified `[]` for this effect, the new effect function wouldn’t run: -```jsx{3} +```jsx {3} useEffect(() => { document.title = 'Hello, ' + name; }, []); // Wrong: name is missing in deps @@ -822,7 +822,7 @@ In this case the problem might seem obvious. But the intuition can fool you in o For example, let’s say we’re writing a counter that increments every second. With a class, our intuition is: “Set up the interval once and destroy it once”. Here’s an [example](https://codesandbox.io/s/n5mjzjy9kl) of how we can do it. When we mentally translate this code to `useEffect`, we instinctively add `[]` to the deps. “I want it to run once”, right? -```jsx{9} +```jsx {9} function Counter() { const [count, setCount] = useState(0); @@ -845,7 +845,7 @@ However, this makes sense if you know that dependencies are our hint to React ab In the first render, `count` is `0`. Therefore, `setCount(count + 1)` in the first render’s effect means `setCount(0 + 1)`. **Since we never re-run the effect because of `[]` deps, it will keep calling `setCount(0 + 1)` every second:** -```jsx{8,12,21-22} +```jsx {8,12,21-22} // First render, state is 0 function Counter() { // ... @@ -884,7 +884,7 @@ We lied to React by saying our effect doesn’t depend on a value from inside ou Our effect uses `count` — a value inside the component (but outside the effect): -```jsx{1,5} +```jsx {1,5} const count = // ... useEffect(() => { @@ -909,7 +909,7 @@ There are two strategies to be honest about dependencies. You should generally s **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: -```jsx{3,6} +```jsx {3,6} useEffect(() => { const id = setInterval(() => { setCount(count + 1); @@ -920,7 +920,7 @@ useEffect(() => { This makes the dependency array correct. It may not be *ideal* but that’s the first issue we needed to fix. Now a change to `count` will re-run the effect, with each next interval referencing `count` from its render in `setCount(count + 1)`: -```jsx{8,12,24,28} +```jsx {8,12,24,28} // First render, state is 0 function Counter() { // ... @@ -972,7 +972,7 @@ Let’s look at a few common techniques for removing dependencies. We want to get rid of the `count` dependency in our effect. -```jsx{3,6} +```jsx {3,6} useEffect(() => { const id = setInterval(() => { setCount(count + 1); @@ -983,7 +983,7 @@ We want to get rid of the `count` dependency in our effect. To do this, we need to ask ourselves: **what are we using `count` for?** It seems like we only use it for the `setCount` call. In that case, we don’t actually need `count` in the scope at all. When we want to update state based on the previous state, we can use the [functional updater form](https://reactjs.org/docs/hooks-reference.html#functional-updates) of `setState`: -```jsx{3} +```jsx {3} useEffect(() => { const id = setInterval(() => { setCount(c => c + 1); @@ -1020,7 +1020,7 @@ Encoding the *intent* (rather than the result) is similar to how Google Docs [so Let’s modify the previous example to have two state variables: `count` and `step`. Our interval will increment the count by the value of the `step` input: -```jsx{7,10} +```jsx {7,10} function Counter() { const [count, setCount] = useState(0); const [step, setStep] = useState(1); @@ -1055,7 +1055,7 @@ When you find yourself writing `setSomething(something => ...)`, it’s a good t Let’s trade the `step` dependency for a `dispatch` dependency in our effect: -```jsx{1,6,9} +```jsx {1,6,9} const [state, dispatch] = useReducer(reducer, initialState); const { count, step } = state; @@ -1077,7 +1077,7 @@ We solved our problem! Instead of reading the state *inside* an effect, it dispatches an *action* that encodes the information about *what happened*. This allows our effect to stay decoupled from the `step` state. Our effect doesn’t care *how* we update the state, it just tells us about *what happened*. And the reducer centralizes the update logic: -```jsx{8,9} +```jsx {8,9} const initialState = { count: 0, step: 1, @@ -1103,7 +1103,7 @@ We’ve seen how to remove dependencies when an effect needs to set state based In fact, we can! We can put *the reducer itself* inside our component to read props: -```jsx{1,6} +```jsx {1,6} function Counter({ step }) { const [count, dispatch] = useReducer(reducer, 0); @@ -1138,7 +1138,7 @@ You may be wondering: how can this possibly work? How can the reducer “know” A common mistake is to think functions shouldn’t be dependencies. For example, this seems like it could work: -```jsx{13} +```jsx {13} function SearchResults() { const [data, setData] = useState({ hits: [] }); @@ -1186,7 +1186,7 @@ function SearchResults() { Now let’s say we later use some state or prop in one of these functions: -```jsx{6} +```jsx {6} function SearchResults() { const [query, setQuery] = useState('react'); @@ -1213,7 +1213,7 @@ If we forget to update the deps of any effects that call these functions (possib Luckily, there is an easy solution to this problem. **If you only use some functions *inside* an effect, move them directly *into* that effect:** -```jsx{4-12} +```jsx {4-12} function SearchResults() { // ... useEffect(() => { @@ -1239,7 +1239,7 @@ So what is the benefit? We no longer have to think about the “transitive depen If we later edit `getFetchUrl` to use the `query` state, we’re much more likely to notice that we’re editing it *inside* an effect — and therefore, we need to add `query` to the effect dependencies: -```jsx{6,15} +```jsx {6,15} function SearchResults() { const [query, setQuery] = useState('react'); @@ -1302,7 +1302,7 @@ In that case you might not want to move `getFetchUrl` inside either of the effec On the other hand, if you’re “honest” about the effect dependencies, you may run into a problem. Since both our effects depend on `getFetchUrl` **(which is different on every render)**, our dependency arrays are useless: -```jsx{2-5} +```jsx {2-5} function SearchResults() { // 🔴 Re-triggers all effects on every render function getFetchUrl(query) { @@ -1329,7 +1329,7 @@ Instead, there are two other solutions that are simpler. **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:** -```jsx{1-4} +```jsx {1-4} // ✅ Not affected by the data flow function getFetchUrl(query) { return 'https://hn.algolia.com/api/v1/search?query=' + query; @@ -1355,7 +1355,7 @@ There’s no need to specify it in deps because it’s not in the render scope a Alternatively, you can wrap it into the [`useCallback` Hook](https://reactjs.org/docs/hooks-reference.html#usecallback): -```jsx{2-5} +```jsx {2-5} function SearchResults() { // ✅ Preserves identity when its own deps are the same const getFetchUrl = useCallback((query) => { @@ -1382,7 +1382,7 @@ Let's see why this approach is useful. Previously, our example showed two search We'll immediately see that it's missing a `query` dependency: -```jsx{5} +```jsx {5} function SearchResults() { const [query, setQuery] = useState('react'); const getFetchUrl = useCallback(() => { // No query argument @@ -1394,7 +1394,7 @@ function SearchResults() { If I fix my `useCallback` deps to include `query`, any effect with `getFetchUrl` in deps will re-run whenever the `query` changes: -```jsx{4-7} +```jsx {4-7} function SearchResults() { const [query, setQuery] = useState('react'); @@ -1416,7 +1416,7 @@ Thanks to `useCallback`, if `query` is the same, `getFetchUrl` also stays the sa This is just a consequence of embracing the data flow and the synchronization mindset. **The same solution works for function props passed from parents:** -```jsx{4-8} +```jsx {4-8} function Parent() { const [query, setQuery] = useState('react'); @@ -1446,7 +1446,7 @@ Since `fetchData` only changes inside `Parent` when its `query` state changes, o Interestingly, this pattern is broken with classes in a way that really shows the difference between the effect and lifecycle paradigms. Consider this translation: -```jsx{5-8,18-20} +```jsx {5-8,18-20} class Parent extends Component { state = { query: 'react' @@ -1475,7 +1475,7 @@ class Child extends Component { You might be thinking: “Come on Dan, we all know that `useEffect` is like `componentDidMount` and `componentDidUpdate` combined, you can’t keep beating that drum!” **Yet this doesn’t work even with `componentDidUpdate`:** -```jsx{8-13} +```jsx {8-13} class Child extends Component { state = { data: null @@ -1515,7 +1515,7 @@ But then `this.props.fetchData !== prevProps.fetchData` is *always* `true`, even The only real solution to this conundrum with classes is to bite the bullet and pass the `query` itself into the `Child` component. The `Child` doesn’t actually end up *using* the `query`, but it can trigger a refetch when it changes: -```jsx{10,22-24} +```jsx {10,22-24} class Parent extends Component { state = { query: 'react' @@ -1591,7 +1591,7 @@ class Article extends Component { As you probably know, this code is buggy. It doesn’t handle updates. So the second classic example you could find online is something like this: -```jsx{8-12} +```jsx {8-12} class Article extends Component { state = { article: null @@ -1622,7 +1622,7 @@ If the async approach you use supports cancellation, that’s great! You can can Alternatively, the easiest stopgap approach is to track it with a boolean: -```jsx{5,9,16-18} +```jsx {5,9,16-18} function Article({ id }) { const [article, setArticle] = useState(null); diff --git a/public/algebraic-effects-for-the-rest-of-us/index.md b/public/algebraic-effects-for-the-rest-of-us/index.md index d26a0b4..d71aea5 100644 --- a/public/algebraic-effects-for-the-rest-of-us/index.md +++ b/public/algebraic-effects-for-the-rest-of-us/index.md @@ -35,7 +35,7 @@ The name might be a bit intimidating but the idea is simple. If you’re familia Let’s recap `try / catch` first. Say you have a function that throws. Maybe there’s a bunch of functions between it and the `catch` block: -```jsx{4,19} +```jsx {4,19} function getName(user) { let name = user.name; if (name === null) { @@ -70,7 +70,7 @@ We’re done. It’s too late. The best we can do is to recover from a failure a This is an example written in a hypothetical JavaScript dialect (let’s call it ES2025 just for kicks) that lets us *recover* from a missing `user.name`: -```jsx{4,19-21} +```jsx {4,19-21} function getName(user) { let name = user.name; if (name === null) { @@ -103,7 +103,7 @@ So what’s happening? Let’s take a closer look. Instead of throwing an error, we *perform an effect*. Just like we can `throw` any value, we can pass any value to `perform`. In this example, I’m passing a string, but it could be an object, or any other data type: -```jsx{4} +```jsx {4} function getName(user) { let name = user.name; if (name === null) { @@ -115,7 +115,7 @@ function getName(user) { When we `throw` an error, the engine looks for the closest `try / catch` error handler up the call stack. Similarly, when we `perform` an effect, the engine would search for the closest `try / handle` *effect handler* up the call stack: -```jsx{3} +```jsx {3} try { makeFriends(arya, gendry); } handle (effect) { @@ -127,7 +127,7 @@ try { This effect lets us decide how to handle the case where a name is missing. The novel part here (compared to exceptions) is the hypothetical `resume with`: -```jsx{5} +```jsx {5} try { makeFriends(arya, gendry); } handle (effect) { @@ -139,7 +139,7 @@ try { This is the part you can’t do with `try / catch`. It lets us **jump back to where we performed the effect, and pass something back to it from the handler**. 🤯 -```jsx{4,6,16,18} +```jsx {4,6,16,18} function getName(user) { let name = user.name; if (name === null) { @@ -194,7 +194,7 @@ So how is that relevant? For a moment, let’s forget about `async / await` and get back to our example: -```jsx{4,19-21} +```jsx {4,19-21} function getName(user) { let name = user.name; if (name === null) { @@ -223,7 +223,7 @@ What if our effect handler didn’t know the “fallback name” synchronously? It turns out, we can call `resume with` asynchronously from our effect handler without making any changes to `getName` or `makeFriends`: -```jsx{19-23} +```jsx {19-23} function getName(user) { let name = user.name; if (name === null) { @@ -264,7 +264,7 @@ This is why so much discussion about algebraic effects is incomprehensible to me They let you write code that focuses on *what* you’re doing: -```jsx{2,3,5,7,12} +```jsx {2,3,5,7,12} function enumerateFiles(dir) { const contents = perform OpenDirectory(dir); perform Log('Enumerating files in ', dir); @@ -282,7 +282,7 @@ function enumerateFiles(dir) { And later wrap it with something that specifies *how*: -```jsx{6-7,9-11,13-14} +```jsx {6-7,9-11,13-14} let files = []; try { enumerateFiles('C:\\'); @@ -323,7 +323,7 @@ Unlike `async / await` or Generators, **algebraic effects don’t require compli Effect handlers let us decouple the program logic from its concrete effect implementations without too much ceremony or boilerplate code. For example, we could completely override the behavior in tests to use a fake filesystem and to snapshot logs instead of outputting them to the console: -```jsx{19-23} +```jsx {19-23} import { withFakeFileSystem } from 'fake-fs'; function withLogSnapshot(fn) { diff --git a/public/before-you-memo/index.md b/public/before-you-memo/index.md index ecb3bc3..3b67056 100644 --- a/public/before-you-memo/index.md +++ b/public/before-you-memo/index.md @@ -53,7 +53,7 @@ I could [put `memo()` on it](https://codesandbox.io/s/amazing-shtern-61tu4?file= If you look at the rendering code closer, you'll notice only a part of the returned tree actually cares about the current `color`: -```jsx{2,5-6} +```jsx {2,5-6} export default function App() { let [color, setColor] = useState('red'); return ( @@ -68,7 +68,7 @@ export default function App() { So let's extract that part into a `Form` component and move state _down_ into it: -```jsx{4,11,14,15} +```jsx {4,11,14,15} export default function App() { return ( <> @@ -97,7 +97,7 @@ Now if the `color` changes, only the `Form` re-renders. Problem solved. The above solution doesn't work if the piece of state is used somewhere *above* the expensive tree. For example, let's say we put the `color` on the *parent* `
Hello
@@ -116,7 +116,7 @@ var fred = new Person('Fred'); // Same object as `this` inside `Person` The `new` operator also makes anything we put on `Person.prototype` available on the `fred` object: -```jsx{4-6,9} +```jsx {4-6,9} function Person(name) { this.name = name; } @@ -244,7 +244,7 @@ new Greeting(); // 🔴 Greeting is not a constructor This behavior is intentional and follows from the design of arrow functions. One of the main perks of arrow functions is that they *don’t* have their own `this` value — instead, `this` is resolved from the closest regular function: -```jsx{2,6,7} +```jsx {2,6,7} class Friends extends React.Component { render() { const friends = this.props.friends; @@ -297,7 +297,7 @@ This, again, has to do with the quirks of the [`new` operator](https://developer However, JavaScript also allows a function called with `new` to *override* the return value of `new` by returning some other object. Presumably, this was considered useful for patterns like pooling where we want to reuse instances: -```jsx{1-2,7-8,17-18} +```jsx {1-2,7-8,17-18} // Created lazily var zeroVector = null; @@ -371,7 +371,7 @@ So the “prototype chain” is more like `__proto__.__proto__.__proto__` than ` What’s the `prototype` property on a function or a class, then? **It’s the `__proto__` given to all objects `new`ed with that class or a function!** -```jsx{8} +```jsx {8} function Person(name) { this.name = name; } @@ -409,7 +409,7 @@ We know that when we say `obj.foo`, JavaScript actually looks for `foo` in `obj` With classes, you’re not exposed directly to this mechanism, but `extends` also works on top of the good old prototype chain. That’s how our React class instance gets access to methods like `setState`: -```jsx{1,9,13} +```jsx {1,9,13} class Greeting extends React.Component { render() { returnHello
; @@ -447,7 +447,7 @@ new Greeting() Since the `__proto__` chain mirrors the class hierarchy, we can check whether a `Greeting` extends `React.Component` by starting with `Greeting.prototype`, and then following down its `__proto__` chain: -```jsx{3,4} +```jsx {3,4} // `__proto__` chain new Greeting() → Greeting.prototype // 🕵️ We start here diff --git a/public/how-does-setstate-know-what-to-do/index.md b/public/how-does-setstate-know-what-to-do/index.md index 8a6bc76..0d25fd3 100644 --- a/public/how-does-setstate-know-what-to-do/index.md +++ b/public/how-does-setstate-know-what-to-do/index.md @@ -7,7 +7,7 @@ cta: 'react' When you call `setState` in a component, what do you think happens? -```jsx{11} +```jsx {11} import React from 'react'; import ReactDOM from 'react-dom'; @@ -112,7 +112,7 @@ Okay, so now we know that the `react` package doesn’t contain anything interes **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: -```jsx{4,9,14} +```jsx {4,9,14} // Inside React DOM const inst = new YourComponent(); inst.props = props; @@ -172,7 +172,7 @@ const React = { And individual renderers set the dispatcher before rendering your component: -```jsx{3,8-9} +```jsx {3,8-9} // In React DOM const prevDispatcher = React.__currentDispatcher; React.__currentDispatcher = ReactDOMDispatcher; diff --git a/public/making-setinterval-declarative-with-react-hooks/index.md b/public/making-setinterval-declarative-with-react-hooks/index.md index 6b3c32b..4c114aa 100644 --- a/public/making-setinterval-declarative-with-react-hooks/index.md +++ b/public/making-setinterval-declarative-with-react-hooks/index.md @@ -30,7 +30,7 @@ If you’re new to Hooks and don’t understand what the fuss is about, check ou Without further ado, here’s a counter that increments every second: -```jsx{6-9} +```jsx {6-9} import React, { useState, useEffect, useRef } from 'react'; function Counter() { @@ -128,7 +128,7 @@ While you wouldn’t necessarily control the delay with an *input*, adjusting it So how would you do this with `setInterval` in a class? I ended up with this: -```jsx{7-26} +```jsx {7-26} class Counter extends React.Component { state = { count: 0, @@ -179,7 +179,7 @@ What’s the Hook version looking like? 🥁🥁🥁 -```jsx{5-8} +```jsx {5-8} function Counter() { let [count, setCount] = useState(0); let [delay, setDelay] = useState(1000); @@ -208,7 +208,7 @@ Yeah, *that’s all it takes*. Unlike the class version, there is no complexity gap for “upgrading” the `useInterval` Hook example to have a dynamically adjusted delay: -```jsx{4,9} +```jsx {4,9} // Constant delay useInterval(() => { setCount(count + 1); @@ -226,7 +226,7 @@ When `useInterval` Hook sees a different delay, it sets up the interval again. What if I want to temporarily *pause* my interval? I can do this with state too: -```jsx{6} +```jsx {6} const [delay, setDelay] = useState(1000); const [isRunning, setIsRunning] = useState(true); @@ -260,7 +260,7 @@ function Counter() { Now I want an interval that increments it every second. It’s a [side effect that needs cleanup](https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup) so I’m going to `useEffect()` and return the cleanup function: -```jsx{4-9} +```jsx {4-9} function Counter() { let [count, setCount] = useState(0); @@ -304,7 +304,7 @@ setInterval(() => { You might know that `useEffect()` lets us [*opt out*](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) of re-applying effects. You can specify a dependency array as a second argument, and React will only re-run the effect if something in that array changes: -```jsx{3} +```jsx {3} useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); @@ -316,7 +316,7 @@ However, this is a common source of mistakes if you’re not very familiar with In the first attempt, our problem was that re-running the effects caused our timer to get cleared too early. We can try to fix it by never re-running them: -```jsx{9} +```jsx {9} function Counter() { let [count, setCount] = useState(0); @@ -364,7 +364,7 @@ Our “impedance mismatch” is not between Databases and Objects. It is between Hooks let us apply the same declarative approach to effects: -```jsx{4} +```jsx {4} // Describes every interval state useInterval(() => { setCount(count + 1); @@ -420,7 +420,7 @@ This mutable `savedCallback` needs to “persist” across the re-renders. So it `useRef()` returns a plain object with a mutable `current` property that’s shared between renders. We can save the *latest* interval callback into it: -```jsx{8} +```jsx {8} function callback() { // Can read fresh props, state, etc. setCount(count + 1); @@ -434,7 +434,7 @@ This mutable `savedCallback` needs to “persist” across the re-renders. So it And then we can read and call it from inside our interval: -```jsx{3,8} +```jsx {3,8} useEffect(() => { function tick() { savedCallback.current(); @@ -449,7 +449,7 @@ Thanks to `[]`, our effect never re-executes, and the interval doesn’t get res Here’s a complete working solution: -```jsx{10,15} +```jsx {10,15} function Counter() { const [count, setCount] = useState(0); const savedCallback = useRef(); @@ -487,7 +487,7 @@ Admittedly, the above code can be disorienting. It’s mind-bending to mix the o Ideally, I just want to write this: -```jsx{4-6} +```jsx {4-6} function Counter() { const [count, setCount] = useState(0); @@ -534,7 +534,7 @@ I will use it when I set up the interval: Now that the `delay` can change between renders, I need to declare it in the dependencies of my interval effect: -```jsx{8} +```jsx {8} useEffect(() => { function tick() { savedCallback.current(); @@ -586,7 +586,7 @@ It does! We can now `useInterval()` in any component and not think too much abou Say we want to be able to pause our interval by passing `null` as the `delay`: -```jsx{6} +```jsx {6} const [delay, setDelay] = useState(1000); const [isRunning, setIsRunning] = useState(true); @@ -597,7 +597,7 @@ Say we want to be able to pause our interval by passing `null` as the `delay`: How do we implement this? The answer is: by not setting up an interval. -```jsx{6} +```jsx {6} useEffect(() => { function tick() { savedCallback.current(); @@ -622,7 +622,7 @@ This `useInterval()` Hook is really fun to play with. When the side effects are  -```jsx{10-15} +```jsx {10-15} function Counter() { const [delay, setDelay] = useState(1000); const [count, setCount] = useState(0); diff --git a/public/my-wishlist-for-hot-reloading/index.md b/public/my-wishlist-for-hot-reloading/index.md index 0753892..6db7c07 100644 --- a/public/my-wishlist-for-hot-reloading/index.md +++ b/public/my-wishlist-for-hot-reloading/index.md @@ -59,7 +59,7 @@ Every time this module re-executes after an edit, `window.latest_Button` would p For a long time, it seemed to me that implementing reliable hot reloading for functions *alone* would encourage people to write convoluted code just to avoid using classes. But with [Hooks](https://reactjs.org/docs/hooks-intro.html), function components are fully featured so this is not a concern anymore. And this approach “just works” with Hooks: -```jsx{4} +```jsx {4} // Reassigns the latest version window.latest_Button = function(props) { // Your actual code is moved here by a plugin diff --git a/public/react-as-a-ui-runtime/index.md b/public/react-as-a-ui-runtime/index.md index d7c9d28..c471898 100644 --- a/public/react-as-a-ui-runtime/index.md +++ b/public/react-as-a-ui-runtime/index.md @@ -134,7 +134,7 @@ When we say `ReactDOM.render(reactElement, domContainer)`, we mean: **“Dear Re React will look at the `reactElement.type` (in our example, `'button'`) and ask the React DOM renderer to create a host instance for it and set the properties: -```jsx{3,4} +```jsx {3,4} // Somewhere in the ReactDOM renderer (simplified) function createHostInstance(reactElement) { let domNode = document.createElement(reactElement.type); @@ -145,7 +145,7 @@ function createHostInstance(reactElement) { In our example, effectively React will do this: -```jsx{1,2} +```jsx {1,2} let domNode = document.createElement('button'); domNode.className = 'blue'; @@ -158,7 +158,7 @@ If the React element has child elements in `reactElement.props.children`, React What happens if we call `ReactDOM.render()` twice with the same container? -```jsx{2,11} +```jsx {2,11} ReactDOM.render( , document.getElementById('container') @@ -208,7 +208,7 @@ This is pretty close to how React thinks about it. Here is an example with comments showing roughly what React does: -```jsx{9,10,16,26,27} +```jsx {9,10,16,26,27} // let domNode = document.createElement('button'); // domNode.className = 'blue'; // domContainer.appendChild(domNode); @@ -250,7 +250,7 @@ If React only reuses host instances when the element types “match up” betwee Say we want to first show only an input, but later render a message before it: -```jsx{12} +```jsx {12} // First render ReactDOM.render(