表示されたスクリーンショットは、プライバシー上の懸念のため、記事のシミュレート問題セクションではなく、元のコードの問題から来ています。 表示されたスクリーンショットは、プライバシー上の懸念のため、記事のシミュレート問題セクションではなく、元のコードの問題から来ています。 ️コンテンツテーブル THE SETUP タイトル: Page Freeze on Input 失敗したデバッグ試み 『The Breakthrough: Pause Script Execution』 原題:The Root Cause: A Loop That Never Ends 冷凍のシミュレーション(Try It Yourself) 学んだこと タグ:Debugging Memory Leaks タグ THE SETUP This bug appeared in a project. React + TypeScript + Redux + RxJS The form had a single numeric field を更新すると、Aを起動しました。 (使用したもの) ) to recalculate the state synced text. quantity Redux selector reselect Total cost Everything looked fine on the サイド Buy しかし、転換することにより、The side caused something bizarre: the page froze instantly when entering even. ページは入力時に即座に凍結します。 . Sell 1 タイトル: Page Freeze on Input 量のフィールドに入力する場合: The UI froze completely The browser tab became unresponsive The in Chrome Performance Monitor. (Sometimes, the JS heap size also keeps increasing) CPU usage 100% これは典型的な「ゆっくり」の render ではありませんでした。 . 完全吊り Chrome eventually showed the “Page Unresponsive” dialog & I had to kill the tab. 失敗したデバッグ試み 一般的なデバッグ方法は役に立たなかった: Attempt Result console.log Never printed anything debugger; Too slow or never triggered React DevTools Profiler Froze with the app Chrome Performance Profiler Couldn’t finish recording Removing components Still froze, even with just the input console.log Never printed anything debugger; 遅すぎるか、決して起動しないか React DevToolsプロフィール Froze with the App(アプリで凍結) Chrome パフォーマンスプロフィール 録音を終えることができなかった。 コンポーネント削除 まだ凍りついている、たとえ入力だけでも The issue had to be a 無限に走るけど、どこへ行くの? loop or recursive render 『The Breakthrough: Pause Script Execution』 そこで私は、JavaScriptのハープが成長し続ければ、 . JavaScript is still running だからオープンした そして、隠れた宝石を用いた。 Chrome DevTools → Sources tab Pause Script Execution (⏸️) Unfortunately, I could not see an explanation of this feature even in the official Chrome DevTools docs: https://developer.chrome.com/docs/devtools/javascript/breakpoint 残念ながら、私は公式のChrome DevToolsドキュメントでさえこの機能の説明を見ることができませんでした: https://developer.chrome.com/docs/devtools/javascript/breakpoint https://developer.chrome.com/docs/devtools/javascript/breakpoint ステップ: Open Chrome DevTools first! You won’t be able to open them during the freeze. Reproduce the freeze (enter quantity). When the tab hangs, open . DevTools → Sources tab Click the icon (top-right). ⏸️ Pause Chrome freezes JS execution . at that exact line Scroll down on the right panel & check the panel to trace which functions are currently executing. Call Stack Scroll through the parent calls to reveal how the function chain started. You can even click on the parent calls to see their invoked line! 原題:The Root Cause: A Loop That Never Ends 停止したステックは、8+の機能の連鎖を明らかにし、 Handles and Ends Within A 使用するA . onChange utility function Redux Reselect selector こちらが犯人: let a = 0; const size = props.size; // expected number, got string while (a < size) { // do something } 出てくる came indirectly from the input value: a まるで . props.size string "5" JSの強制力の奇妙さのために、ループ比較は一定の条件下で外に出ることができず、無限のループを引き起こし、全線を凍結しました。 それを修正することは、使用前に値を数字に変換するのと同じくらい簡単でした。 const size = Number(props.size); ページの凍結がすぐに消えてしまいました。 冷凍のシミュレーション(Try It Yourself) You can recreate this exact bug and try the debugging trick yourself by going to this codesandbox. あなたはこの正確なバグを再生し、このコードサンドボックスへ行ってデバッグトリックを自分で試すことができます。 OR running the below code in a new まず、この仕事を守るため、 hang your browser tab 😅 リンク Create React App, ウィル リンク import { useState } from "react"; export default function App() { const [quantity, setQuantity] = useState(""); const handleChange = (e) => { const value = e.target.value; setQuantity(value); const end = Date.now() + 145000; let a = 0; // ❌ Intentional infinite loop while (Date.now() < end) { // Busy-wait a++; } console.log("Done!"); // never reached }; return ( <div style={{ padding: 20 }}> <h2>🧊 Simulate a Page Freeze</h2> <input type="text" placeholder="Enter quantity" value={quantity} onChange={handleChange} /> <p>Type any number and watch Chrome suffer.</p> </div> ); } 再生するためのステップ このコードを上記の codesandbox またはローカルで開きます。 入力のいずれかの番号を入力します。 FREEZE SOLIDのタブをご覧ください。 Chrome DevTools → Sources タブ → ️ Pause script execution を開きます。 Call Stack の handleChange 内の無限のループを観察してください。 学んだこと 何もしないとき:スクリプトの執行を休止することは銀の弾です。 無限のループは、UIから遠く離れた選択器、削減器、またはユーティリティファイルの中に隠れることができます。 Always sanitize and type-check user input before computations. ループは鋭いツールですが、1つの間違った状態で、あなたのアプリはCPUトースターになります。 タグ:Debugging Memory Leaks 同じテクニックが遅い追跡を助けるかもしれない JSの積み重ねが徐々に増加する場合 memory leaks 空き時間中にスクリプトの実行を停止すると、どのバックグラウンドプロセスやサブスクリプションがまだ不必要に実行されているかを明らかにする可能性があります。 しかし、これは別の記事のための実験です 😉。