ホームページ > 記事 > ウェブフロントエンド > React Hooks アプリケーションのバックグラウンド処理に Web ワーカーを利用する。
React の Web ワーカーは、React アプリケーションで複数のスレッドを同時に実行できるようにする機能です。これにより、一部のスレッドがバックグラウンドで実行され、メイン スレッドの一部として実行されないようになります。
たとえば、現在実行中のメインスレッドの通常の機能を変更せずに、複雑な計算、API からの大量のデータの取得、またはバックグラウンド通知の実装を実行したいアプリケーションがあるとします。これは、これらすべてのプロセスが React アプリで実行されている間にユーザー インターフェイスがフリーズしないようにする React Web フックを実装することで実現できます。
このガイドでは、指数計算を実行するカスタム反応フックに Web ワーカーを実装するサンプル反応プロジェクトを作成します。
反応アプリケーションを作成します。
npx create-vite myproject -- --template react
create-react-app と比較して実行時間が速いため、vite を使用して反応アプリを作成することを好みます。
ここでは、vite のテンプレートとして React を使用します。
JavaScript を選択します:
エディタでプロジェクトを開きます。 (このプロジェクトでは Vs コードを使用します)
code .
src ディレクトリ内に、別のディレクトリ hooks/useWebWorkers を作成します。
このフォルダー内に、以下に示すように Web ワーカーを保持する Index.js ファイルを作成します。
/hooks/useWebWorker/index.js 内に、Web ワーカーを作成するカスタム フックを作成します
workerFunction と inputData をパラメータとして受け取る useWebWorker カスタム フックを作成します。
const useWebWorker =(workerFunction,inputData)=>{ } export default useWebWorker;
useState フックを使用して、Web ワーカーの結果、エラー、ステータスの状態を初期化します。
import {useState} from 'react' const useWebWorker =(workerFunction,inputData)=>{ const [result,setResult] = useState(null); const [error,setError] = useState(null); const [loading,setLoading] = useState(false); } export default useWebWorker;
i) result には、Web ワーカーの結果が保存されます。最初は null に設定されます。
ii)error は、Web ワーカーで発生する可能性のあるエラーを追跡します。最初は null に設定されます。
iii) ロードすると、データを処理しているかどうかに関係なく、Web ワーカーの状態が得られます。最初は false に設定されます。
Web ワーカーを保持する useEffect を初期化します。
import {useState,useEffect} from 'react' const useWebWorker =(workerFunction,inputData)=>{ const [result,setResult] = useState(null); const [error,setError] = useState(null); const [loading,setLoading] = useState(false); useEffect(()=>{ },[inputData]) } export default useWebWorker;
useEffect フックは区切り文字として設定されているため、inputData が変更されるたびに実行されます。
inputData が null または未定義の場合、フックは早期に終了します。
if(!inputData)return;
すべての状態が正しくリセットされていることを確認してください
setLoading(true); setError(null); setResult(null);
const blob = new Blob( [ ` self.onmessage = function(event) { (${workerFunction.toString()})(event); }; `, ], { type: "application/javascript" } );
workerFunction を文字列に変換し、Blob オブジェクトに含めます。この Blob は、Web Worker で実行される JavaScript コードを表します。
Blob の URL を生成し、この URL を使用して新しい Web ワーカーを作成するワーカーを作成します。
const workerScriptUrl = URL.createObjectURL(blob); const worker = new Worker(workerScriptUrl);
ワーカーによって発行されたメッセージのイベント ハンドラーを設定します。
worker.onmessage(event){ }
Web ワーカーが (postMessage を使用して) メイン スレッドにメッセージを送信すると、イベント ハンドラーがトリガーされます。
event.data には、Web ワーカーの有効な結果またはエラーが含まれています。 if-else ステートメント内でエラーまたは有効な結果のレンダリングを処理します。
エラーが発生した場合は、setError() 内のevent.data.error にエラーを設定します。
有効な結果が返された場合は、結果を setResult()
内のevent.data に渡します。
worker.onmessage = (event) => { console.log("Worker result:", event.data); if (event.data.error) { setError(event.data.error); } else { setResult(event.data); } setLoading(false); };
完了すると読み込みを false に設定します。
worker.onerror(event){
を使用します}
イベントをパラメータとして渡し、エラーをevent.messageに更新し、読み込み状態をfalseに更新します。
worker.onerror = (event) => { console.error("Worker error:", event.message); setError(event.message); setLoading(false); };
ここで、inputData を Web ワーカーに送信します
worker.postMessage(inputData);
コンポーネントがアンマウントされるか、inputData または WorkerFunction が変更されると、Web Worker を終了し、Blob URL を取り消します。
return () => { worker.terminate(); URL.revokeObjectURL(workerScriptUrl); }; }, [inputData, workerFunction]);
結果、エラー、ロード状態を返すことで、最終的に Web ワーカーの状態を返します。
return {result,error,loading}
useWebWorker をエクスポートします:
export default useWebWorker;
以下は、hooks/useWebWorker/index.js の完全なコードです:
import { useState, useEffect } from "react"; const useWebWorker = (workerFunction, inputData) => { const [result, setResult] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { if (!inputData) return; setLoading(true); setError(null); setResult(null); const blob = new Blob( [ ` self.onmessage = function(event) { (${workerFunction})(event); }; `, ], { type: "application/javascript" } ); const workerScriptUrl = URL.createObjectURL(blob); const worker = new Worker(workerScriptUrl); worker.onmessage = (event) => { console.log("Worker result:", event.data); setResult(event.data); setLoading(false); }; worker.onerror = (event) => { console.error("Worker error:", event.message); setError(event.message); setLoading(false); }; console.log("Posting message to worker:", inputData); worker.postMessage(inputData); return () => { worker.terminate(); URL.revokeObjectURL(workerScriptUrl); }; }, [inputData, workerFunction]); return { result, error, loading }; }; export default useWebWorker;
App.jsx で、Web ワーカーによって実行されるワーカー関数を定義しましょう。
const workerFunction = (e) => { const { base, exponent } = e.data; console.log("Worker function received data:", base, exponent); let result = 1; for (let i = 0; i < exponent; i++) { result *= base; } self.postMessage(result); };
e.data contains data from the web worker.
The workerFunction:
Logs the received data (base and exponent).
Computes the power of base raised to exponent.
Sends the result back to the main thread using self.postMessage(result).
Let's now define our App functional component inside our App.jsx:
const App = () => { const [base, setBase] = useState(""); const [exponent, setExponent] = useState(""); const [inputData, setInputData] = useState(null); const { result, error, loading } = useWebWorker(workerFunction, inputData);
base: Stores the base number input.
exponent: Stores the exponent number input.
inputData: Stores the data to be sent to the worker.
Custom Hook Usage: useWebWorker is used to create a Web Worker and manage its state.
const handleBaseChange = (e) => setBase(e.target.value); const handleExponentChange = (e) => setExponent(e.target.value);
handleBaseChange: Updates base state when the input value changes.
handleExponentChange: Updates exponent state when the input value changes
const handleCalculate = () => { setInputData({ base: Number(base), exponent: Number(exponent) }); };
handleCalculate Function: Converts base and exponent to numbers and sets them as inputData for the Web Worker.
return ( <div> <h1>Exponential Calculation with Web Worker</h1> <div> <label> Base: <input type="number" value={base} onChange={handleBaseChange} /> </label> </div> <div> <label> Exponent: <input type="number" value={exponent} onChange={handleExponentChange} /> </label> </div> <button onClick={handleCalculate}>Calculate</button> {loading && <div>Loading...</div>} {error && <div>Error: {error}</div>} {!loading && !error && result !== null && <div>Result: {result}</div>} </div> ); };
JSX Layout:
Displays a title and input fields for base and exponent.
A button triggers the handleCalculate function.
Conditionally renders loading, error, or result messages based on the state.
Below is the complete App.jsx code:
import { useState } from "react"; import useWebWorker from "./hooks/useWebWorker"; import "./App.css"; const workerFunction = (e) => { const { base, exponent } = e.data; console.log("Worker function received data:", base, exponent); let result = 1; for (let i = 0; i < exponent; i++) { result *= base; } self.postMessage(result); }; const App = () => { const [base, setBase] = useState(""); const [exponent, setExponent] = useState(""); const [inputData, setInputData] = useState(null); const { result, error, loading } = useWebWorker(workerFunction, inputData); const handleBaseChange = (e) => setBase(e.target.value); const handleExponentChange = (e) => setExponent(e.target.value); const handleCalculate = () => { setInputData({ base: Number(base), exponent: Number(exponent) }); }; return ( <div> <h1>Exponential Calculation with Web Worker</h1> <div> <label> Base: <input type="number" value={base} onChange={handleBaseChange} /> </label> </div> <div> <label> Exponent: <input type="number" value={exponent} onChange={handleExponentChange} /> </label> </div> <button onClick={handleCalculate}>Calculate</button> {loading && <div>Loading...</div>} {error && <div>Error: {error}</div>} {!loading && !error && result !== null && <div>Result: {result}</div>} </div> ); }; export default App;
We can now use npm run dev to view our project.
Below is a live preview of our project:
Web Workers Project Implementation
Implementing Web Workers in your React applications can significantly enhance performance, especially when dealing with CPU-intensive tasks. By offloading such tasks to background threads, you ensure that your app remains responsive and provides a smooth user experience.
In our example, we've seen how straightforward it can be to set up and use Web Workers in a React environment. From dynamically creating a worker using a custom hook to managing the communication between the main thread and the worker, every step is designed to be both efficient and easy to integrate.
This approach not only helps in maintaining a responsive UI but also makes your app more robust and user-friendly. Whether it's for complex calculations, data processing, or any other heavy lifting, Web Workers can be your go-to solution for multitasking in modern web applications.
Remember, the key to a great user experience is not just about what your app does but how it feels while doing it. By implementing Web Workers, you can ensure that your app feels snappy and responsive, keeping your users happy and engaged. So, go ahead and explore the power of Web Workers in your next React project – your users will thank you for it!
以上がReact Hooks アプリケーションのバックグラウンド処理に Web ワーカーを利用する。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。