Resurshantering med Reacts use-Hook: Optimera resurslivscykler för topprestanda | MLOG | MLOG

Förklaring:

Exempel 2: Hantera WebSocket-anslutningar

Detta exempel demonstrerar hur man hanterar en WebSocket-anslutning med hjÀlp av "use"-Hooken och ett anpassat resursomslag.

            import React, { useState, useEffect, use } from 'react';

const createWebSocketResource = (url) => {
  let socket;
  let status = 'pending';
  let messageQueue = [];
  let listeners = [];

  const connect = () => {
    return new Promise((resolve, reject) => {
      socket = new WebSocket(url);

      socket.onopen = () => {
        status = 'connected';
        resolve();
        // Skicka köade meddelanden
        messageQueue.forEach(msg => socket.send(msg));
        messageQueue = [];
      };

      socket.onerror = (error) => {
        status = 'error';
        reject(error);
      };

      socket.onmessage = (event) => {
        listeners.forEach(listener => listener(event.data));
      };

      socket.onclose = () => {
        status = 'closed';
        listeners = []; // Rensa lyssnare för att undvika minneslÀckor
      };
    });
  };

  const promise = connect();

  return {
    read() {
      use(promise);
    },
    send(message) {
      if (status === 'connected') {
        socket.send(message);
      } else {
        messageQueue.push(message);
      }
    },
    subscribe(listener) {
      listeners.push(listener);
      return () => {
        listeners = listeners.filter(l => l !== listener);
      };
    },
    close() {
        if (socket && socket.readyState !== WebSocket.CLOSED) {
            socket.close();
        }
    }
  };
};

function WebSocketComponent({ url }) {
  const socketResource = createWebSocketResource(url);
  // Pausa (suspend) tills ansluten
  socketResource.read();
  const [message, setMessage] = useState('');
  const [receivedMessages, setReceivedMessages] = useState([]);

  useEffect(() => {
    const unsubscribe = socketResource.subscribe(data => {
      setReceivedMessages(prevMessages => [...prevMessages, data]);
    });
    return () => {
        unsubscribe();
        socketResource.close();
    };
  }, [socketResource]);

  const sendMessage = () => {
    socketResource.send(message);
    setMessage('');
  };

  return (
    
setMessage(e.target.value)} />
Received Messages:
    {receivedMessages.map((msg, index) => (
  • {msg}
  • ))}
); } function App() { return ( Connecting to WebSocket...
}> ); } export default App;

Förklaring:

Exempel 3: Hantera filreferenser (File Handles)

Detta exempel illustrerar resurshantering med "use"-Hooken med hjÀlp av NodeJS filreferenser (Detta fungerar endast i en NodeJS-miljö och Àr avsett att visa koncept för resurslivscykel).

            // Detta exempel Àr utformat för en NodeJS-miljö

const fs = require('node:fs/promises');
import React, { use } from 'react';

const createFileHandleResource = async (filePath) => {
  let fileHandle;

  const openFile = async () => {
    fileHandle = await fs.open(filePath, 'r');
    return fileHandle;
  };

  const promise = openFile();

  return {
    read() {
      return use(promise);
    },
    async close() {
      if (fileHandle) {
        await fileHandle.close();
        fileHandle = null;
      }
    },
    async readContents() {
      const handle = use(promise);
      const buffer = await handle.readFile();
      return buffer.toString();
    }
  };
};


function FileViewer({ filePath }) {
  const fileHandleResource = createFileHandleResource(filePath);
  const contents = fileHandleResource.readContents();

  React.useEffect(() => {
    return () => {
      // Rensning nÀr komponenten avmonteras
      fileHandleResource.close();
    };
  }, [fileHandleResource]);

  return (
    

File Contents:

{contents}
); } // Example Usage async function App() { const filePath = 'example.txt'; await fs.writeFile(filePath, 'Hello, world!\nThis is a test file.'); return (
); } export default App;

Förklaring:

Avancerade tekniker: Error Boundaries, resurspoolning och Server Components

Utöver de grundlÀggande exemplen kan "use"-Hooken kombineras med andra React-funktioner för att implementera mer sofistikerade strategier för resurshantering.

Error Boundaries: Hantera fel elegant

Error boundaries Àr React-komponenter som fÄngar JavaScript-fel var som helst i sitt underordnade komponenttrÀd, loggar dessa fel och visar ett fallback-grÀnssnitt istÀllet för att hela komponenttrÀdet kraschar. NÀr du anvÀnder "use"-Hooken Àr det avgörande att omsluta dina komponenter med error boundaries för att hantera potentiella fel under datahÀmtning eller resursinitialisering.

            import React, { Component } from 'react';

class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Uppdatera state sÄ att nÀsta rendering visar fallback-grÀnssnittet.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // Du kan ocksÄ logga felet till en felrapporteringstjÀnst
    console.error(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // Du kan rendera vilket anpassat fallback-grÀnssnitt som helst
      return 

Something went wrong.

; } return this.props.children; } } function App() { return ( Loading...
}> ); }

Resurspoolning: Optimera ÄteranvÀndning av resurser

I vissa scenarier kan det vara kostsamt att ofta skapa och förstöra resurser. Resurspoolning innebĂ€r att man underhĂ„ller en pool av Ă„teranvĂ€ndbara resurser för att minimera omkostnaderna för att skapa och förstöra resurser. Även om "use"-hooken inte i sig implementerar resurspoolning, kan den anvĂ€ndas tillsammans med en separat implementering av en resurspool.

TÀnk pÄ en databasanslutningspool. IstÀllet för att skapa en ny anslutning för varje förfrÄgan kan du upprÀtthÄlla en pool av för-etablerade anslutningar och ÄteranvÀnda dem. "use"-Hooken kan anvÀndas för att hantera förvÀrv och frigöring av anslutningar frÄn poolen.

(Konceptuellt exempel - implementeringen varierar beroende pÄ den specifika resursen och poolningsbiblioteket):

            // Konceptuellt exempel (inte en komplett, körbar implementation)

import React, { use } from 'react';
// Antag att ett bibliotek för databasanslutningspool finns
import { getConnectionFromPool, releaseConnectionToPool } from './dbPool';

const createDbConnectionResource = () => {
  let connection;

  const acquireConnection = async () => {
    connection = await getConnectionFromPool();
    return connection;
  };

  const promise = acquireConnection();

  return {
    read() {
      return use(promise);
    },
    release() {
      if (connection) {
        releaseConnectionToPool(connection);
        connection = null;
      }
    },
    query(sql) {
      const conn = use(promise);
      return conn.query(sql);
    }
  };
};

function MyDataComponent() {
  const dbResource = createDbConnectionResource();

  React.useEffect(() => {
    return () => {
      dbResource.release();
    };
  }, [dbResource]);

  const data = dbResource.query('SELECT * FROM my_table');
  return 
{data}
; }

React Server Components (RSCs): Det naturliga hemmet för "use"-Hooken

"use"-Hooken var ursprungligen designad för React Server Components. RSCs körs pÄ servern, vilket gör att du kan hÀmta data och utföra andra server-side-operationer utan att skicka kod till klienten. Detta förbÀttrar prestandan avsevÀrt och minskar storleken pÄ JavaScript-paketen pÄ klientsidan.

I RSCs kan "use"-Hooken anvÀndas för att direkt hÀmta data frÄn databaser eller API:er utan behov av klient-side-hÀmtningsbibliotek. Datan hÀmtas pÄ servern, och den resulterande HTML-koden skickas till klienten, dÀr den hydreras av React.

NÀr du anvÀnder "use"-Hooken i RSCs Àr det viktigt att vara medveten om begrÀnsningarna hos RSCs, sÄsom bristen pÄ klient-side state och hÀndelsehanterare. RSCs kan dock kombineras med klientkomponenter för att skapa kraftfulla och effektiva applikationer.

BÀsta praxis för effektiv resurshantering med "use"

För att maximera fördelarna med "use"-Hooken för resurshantering, följ dessa bÀsta praxis:

Vanliga fallgropar och hur man undviker dem

Även om "use"-Hooken erbjuder mĂ„nga fördelar Ă€r det viktigt att vara medveten om potentiella fallgropar och hur man undviker dem.

Slutsats: Omfamna "use"-Hooken för optimerade React-applikationer

Reacts "use"-Hook representerar ett betydande framsteg inom resurshantering i React-applikationer. Genom att förenkla hanteringen av asynkron data, automatisera resursrensning och integreras sömlöst med Suspense, ger den utvecklare möjlighet att bygga mer prestandaorienterade, underhÄllbara och anvÀndarvÀnliga applikationer.

Genom att förstÄ de grundlÀggande koncepten, utforska praktiska exempel och följa bÀsta praxis kan du effektivt utnyttja "use"-Hooken för att optimera resurslivscykler och frigöra den fulla potentialen i dina React-applikationer. I takt med att React fortsÀtter att utvecklas kommer "use"-Hooken utan tvekan att spela en allt viktigare roll i att forma framtiden för resurshantering i React-ekosystemet.