Reactのdocを読む ~Learn~
読んでいく
Without parentheses, any code on the lines after return will be ignored!
複数行でreturn
の括弧無かったら動かないのか、知らなかった
Components can render other components, but you must never nest their definitions:
export default function Gallery() { // 🔴 Never define a component inside another component! function Profile() { // ... } // ... }
The snippet above is very slow and causes bugs. Instead, define every component at the top level:
export default function Gallery() { // ... } // ✅ Declare components at the top level function Profile() { // ... }
When a child component needs some data from a parent, pass it by props instead of nesting definitions.
コンポーネントの中でコンポーネントを定義できるが速度が遅くなるのとバグが発生する
JSX and React are two separate things. They’re often used together, but you can use them independently of each other.
関連記事として下記が紹介されている
これにより、JSXを使うためにReactをimportしなくても良くなった
React assumes that every component you write is a pure function.
よく見るやつ
React offers a “Strict Mode” in which it calls each component’s function twice during development. By calling the component functions twice, Strict Mode helps find components that break these rules.
Strict Modeはコンポーネントを2回レンダリングするから冪等性を違反していないかわかるのか
https://react.dev/learn/keeping-components-pure#where-you-can-cause-side-effects
If you’ve exhausted all other options and can’t find the right event handler for your side effect, you can still attach it to your returned JSX with a useEffect call in your component. This tells React to execute it later, after rendering, when side effects are allowed. However, this approach should be your last resort.
When possible, try to express your logic with rendering alone. You’ll be surprised how far this can take you!
useEffectはなるべく使わないようにする
That event object also lets you stop the propagation. If you want to prevent an event from reaching parent components, you need to call e.stopPropagation() like this Button component does:
イベントの伝播を止める
In rare cases, you might need to catch all events on child elements, even if they stopped propagation. For example, maybe you want to log every click to analytics, regardless of the propagation logic. You can do this by adding Capture at the end of the event name:
伝播を止められたイベントを取得する onClickCapture
がある
Internally, React holds an array of state pairs for every component. It also maintains the current pair index, which is set to 0 before rendering. Each time you call useState, React gives you the next state pair and increments the index.
useState
は内部で持っている配列で管理している
When your app starts, you need to trigger the initial render. Frameworks and sandboxes sometimes hide this code, but it’s done by calling createRoot with the target DOM node, and then calling its render method with your component:
createRoot
のrender
を呼ぶことで初期レンダリングしている
下記を呼んでいる
This process is recursive: if the updated component returns some other component, React will render that component next, and if that component also returns something, it will render that component next, and so on. The process will continue until there are no more nested components and React knows exactly what should be displayed on screen.
レンダリングは親から子に再帰的に実行される
After rendering is done and React updated the DOM, the browser will repaint the screen. Although this process is known as “browser rendering”, we’ll refer to it as “painting” to avoid confusion throughout the docs.
React の一連の動作が終わるとブラウザがレンダリングを行う
After the event handler completes, React will trigger a re-render. During the re-render, React will process the queue. Updater functions run during rendering, so updater functions must be pure and only return the result. Don’t try to set state from inside of them or run other side effects. In Strict Mode, React will run each updater function twice (but discard the second result) to help you find mistakes.
イベントハンドラーの動作が終わってからstateの更新が行われ再レンダリングされる
updater functionはキューに積まれ、レンダリング中に処理される
The draft provided by Immer is a special type of object, called a Proxy, that “records” what you do with it. This is why you can mutate it freely as much as you like! Under the hood, Immer figures out which parts of the draft have been changed, and produces a completely new object that contains your edits.
In computer science, you may hear about a “state machine” being in one of several “states”. If you work with a designer, you may have seen mockups for different “visual states”. React stands at the intersection of design and computer science, so both of these ideas are sources of inspiration.
“Mirroring” props into state only makes sense when you want to ignore all updates for a specific prop. By convention, start the prop name with initial or default to clarify that its new values are ignored:
function Message({ initialColor }) { // The `color` state variable holds the *first* value of `initialColor`. // Further changes to the `initialColor` prop are ignored. const [color, setColor] = useState(initialColor);
初期の値しか使わないpropsはinitial
やdefault
を接頭辞で命名する
You can nest state as much as you like, but making it “flat” can solve numerous problems. It makes state easier to update, and it helps ensure you don’t have duplication in different parts of a nested object.
stateはネストさせない方が管理しやすい
When writing a component, consider which information in it should be controlled (via props), and which information should be uncontrolled (via state). But you can always change your mind and refactor later.
親コンポーネントから管理できる(props を渡す)子コンポーネントを controlled 、親コンポーネントから管理できない(state を持つ)子コンポーネントを uncontrolled と呼ぶ
For each unique piece of state, you will choose the component that “owns” it. This principle is also known as having a “single source of truth”. It doesn’t mean that all state lives in one place—but that for each piece of state, there is a specific component that holds that piece of information. Instead of duplicating shared state between components, lift it up to their common shared parent, and pass it down to the children that need it.
Browsers use many tree structures to model UI. The DOM represents HTML elements, the CSSOM does the same for CSS. There’s even an Accessibility tree!
React preserves a component’s state for as long as it’s being rendered at its position in the UI tree. If it gets removed, or a different component gets rendered at the same position, React discards its state.
コンポーネントが消えたり、別のコンポーネントに置き換えると保持していた state が消える
It’s the same component at the same position, so from React’s perspective, it’s the same counter.
同じ場所にレンダリングされた同じコンポーネントの state は保持する(JSX の構造ではなく UI tree を見る)
As a rule of thumb, if you want to preserve the state between re-renders, the structure of your tree needs to “match up” from one render to another. If the structure is different, the state gets destroyed because React destroys state when it removes a component from the tree.
子コンポーネントが同じでも親コンポーネントが変化すると state は保持されない
But keys let you tell React that this is not just a first counter, or a second counter, but a specific counter
key を使うことで同じコンポーネントが同じ場所に現れても区別できる
When a piece of information is used for rendering, keep it in state. When a piece of information is only needed by event handlers and changing it doesn’t require a re-render, using a ref may be more efficient.
レンダリングで使うなら state、イベントハンドラで必要で変更しても再レンダリングしなくても良い場合は ref を使うと良い
The useRef Hook returns an object with a single property called current. Initially, myRef.current will be null. When React creates a DOM node for this <div>, React will put a reference to this node into myRef.current.
myRef.current
にノードへの参照先が入る
Another solution is to pass a function to the ref attribute. This is called a ref callback. React will call your ref callback with the DOM node when it’s time to set the ref, and with null when it’s time to clear it. This lets you maintain your own array or a Map, and access any ref by its index or some kind of ID.
This happens because by default React does not let a component access the DOM nodes of other components. Not even for its own children! This is intentional. Refs are an escape hatch that should be used sparingly. Manually manipulating another component’s DOM nodes makes your code even more fragile.
Instead, components that want to expose their DOM nodes have to opt in to that behavior. A component can specify that it “forwards” its ref to one of its children. Here’s how MyInput can use the forwardRef API:
他のコンポーネントにアクセスする際はforwardRef
を使う
Here, realInputRef inside MyInput holds the actual input DOM node. However, useImperativeHandle instructs React to provide your own special object as the value of a ref to the parent component. So inputRef.current inside the Form component will only have the focus method. In this case, the ref “handle” is not the DOM node, but the custom object you create inside useImperativeHandle call.
useImperativeHandle
でrefの動作を制御できる
React sets ref.current during the commit. Before updating the DOM, React sets the affected ref.current values to null. After updating the DOM, React immediately sets them to the corresponding DOM nodes.
refに値が設定されるのはDOM更新後
This will instruct React to update the DOM synchronously right after the code wrapped in flushSync executes.
flushSync
でDOMの更新を同期的に行える
React compares the dependency values using the Object.is comparison. See the useEffect reference for details.
useEffect
の依存配列の比較はObject.is
メソッドで行われる
React always cleans up the previous render’s Effect before the next render’s Effect
レンダリング時に毎回 clean up 関数が呼ばれる
In addition to ignoring the result of an outdated API call, you can also use AbortController to cancel the requests that are no longer needed. However, by itself this is not enough to protect against race conditions. More asynchronous steps could be chained after the fetch, so using an explicit flag like ignore is the most reliable way to fix this type of problems.
API 呼び出しのクリーンアップ処理はAbortController
を使っても良いが fetch 関数の連鎖を考えると明示的に ignore フラグを使うようが良い