Skip to content
CannonReactHooks

useStreaming

Introduction

The useStreaming hook is a custom React Hook that simplifies the process of handling streaming requests and managing loading and errors. It is particularly useful when you need to receive data from a server or API using a streaming response and want to manage the loading and error states in your React components efficiently.

Usage

import React from "react";
import { useStreaming } from "@cannonui/reacthooks";

const TestUseStreaming = () => {
  const [streamedData, setStreamedData] = React.useState("");
  const textDecoder = new TextDecoder();

  // Function to be called on each chunk of data received during streaming
  const onDataChunk = (dataChunk: ReadableStreamReadResult<any>) => {
    setStreamedData((prev) => prev + textDecoder.decode(dataChunk.value));
  };

  const { err, res, isLoading } = useStreaming(
    "http://localhost:3001/streaming",
    {
      onDataChunk,
    }
  );

  return (
    <>
      <div>isLoading: {isLoading ? "true" : "false"}</div>
      {err ? <div>Error: {err.message}</div> : <div>no error</div>}
      <div>res: {res ? res.data : ""}</div>
      <div>{streamedData}</div>
    </>
  );
};

export default TestUseStreaming;

Server Mockup using Express

Here’s an example of how you can set up a server mockup using Express to handle the streaming request:

const express = require("express");
const app = express();
const bodyParser = require("body-parser");

// Middleware to parse incoming JSON data
app.use(bodyParser.json());

// Streaming endpoint to handle the request
app.get("/streaming", (req, res) => {
  // Send response as a stream of data
  const data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ666666";
  const chunkSize = 16;
  const interval = 500; // 500ms delay between each chunk

  // Set response headers
  res.setHeader("Content-Type", "text/plain");
  res.setHeader("Content-Length", data.length);

  // Send chunks of data at regular intervals
  let currentIndex = 0;
  const sendChunk = () => {
    const chunk = data.slice(currentIndex, currentIndex + chunkSize);
    currentIndex += chunkSize;
    console.log(currentIndex, data.length);

    // If there's still data to send
    if (currentIndex <= data.length) {
      res.write(chunk);
      setTimeout(sendChunk, interval);
    } else {
      console.log("end");
      // End the response when all data has been sent
      return res.end();
    }
  };

  // Start sending data
  sendChunk();
});

// Start the server on port 3001
app.listen(3001, () => {
  console.log("Server is running on http://localhost:3001");
});

Return Value

The useStreaming hook returns an object containing the following properties:

NameTypeDescription
resResponseData | nullThe response data from the streaming request, if any.
isLoadingbooleanA boolean indicating whether the request is loading.
errError | nullThe error object in case of an error, if any.

Parameters

NameTypeDescription
urlstringThe URL to which the streaming request will be sent.
configExtendedRequestOptions (optional)Additional configuration for the streaming request.

Extended Request Options

The config parameter of the useGet hook allows you to customize the behavior of the GET request using the following properties:

NameTypeDescription
debounce(optional)numberThe time in milliseconds to wait before sending the request after the last trigger. Defaults to undefined.
polling(not available yet)numberThe interval in milliseconds between periodic GET requests. Allows periodic polling for updated data. Defaults to undefined.
tabularTabularFormat (optional)An optional object specifying the format of tabular data if your API returns data in a tabular format.
params(optional)Record<string, string | number>Additional parameters to be sent along with the GET request. Used for pagination or filtering.
data(optional)anyData to be sent as the request body. Useful for sending data in POST requests. Defaults to undefined.
files(optional)File[] (optional)An array of File objects representing files to be uploaded in a file upload request.
isFormData(optional)booleanA flag indicating whether the request body is of type FormData. Defaults to false.
timeout(optional)numberThe timeout duration in milliseconds for the GET request. If the request takes longer, it will be aborted. Defaults to undefined.
offline(not available yet)boolean (optional)A flag to indicate whether to store and serve the request from cache when the device is offline. Defaults to false.
onDataChunk(optional)(chunk: ReadableStreamReadResult<any>)A function to process chunks of data as they arrive when using streaming responses. Defaults to undefined.
onBefore(optional)Array<(params: ExtendedRequestOptions) => any>An array of functions to be executed before sending the GET request. Defaults to an empty array.
onSuccess(optional)Array<(data: any, params: ExtendedRequestOptions) => any>An array of functions to be executed when the GET request is successful. Defaults to an empty array.
onError(optional)(error: Error)A function to be executed when an error occurs during the GET request. Defaults to undefined.
onFinally(optional)(params: ExtendedRequestOptions, data: any, error: any) => voidA function to be executed after the GET request is completed, regardless of success or error. Defaults to undefined.
maxRetry(optional)number (optional)The maximum number of times to retry the GET request in case of network errors. Defaults to undefined.
body(optional)BodyInit | nullThe request body to be sent with the GET request. Can be null.
cache(optional)RequestCacheA string indicating how the request will interact with the browser’s cache to set request’s cache.
credentials (optional)RequestCredentialsA string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request’s credentials.
headers (optional)HeadersInitA Headers object, an object literal, or an array of two-item arrays to set request’s headers.
integrity(optional)stringA cryptographic hash of the resource to be fetched by request. Sets request’s integrity.
keepalive(optional)booleanA boolean to set request’s keepalive.
method (optional)stringA string to set request’s method.
mode (optional)RequestModeA string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request’s mode.
redirect(optional)RequestRedirectA string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request’s redirect.
referrer(optional)stringA string whose value is a same-origin URL, “about
”, or the empty string, to set request’s referrer.
referrerPolicy(optional)ReferrerPolicyA referrer policy to set request’s referrerPolicy.
signal (optional)AbortSignal | nullAn AbortSignal to set request’s signal.
window (optional)nullCan only be null. Used to disassociate request from any Window.

Features

  • Simplifies making streaming requests in React components, making it easy to receive and process data from servers or APIs.
  • Automatically handles the loading state, allowing you to display a loading indicator while the streaming request is ongoing.
  • Provides an error object to handle and display any errors that occur during the streaming request.
  • Can be customized using the optional config parameter to add additional headers, set a timeout, or handle request retries.

Example

In the TestUseStreaming component, we use the useStreaming hook to make a streaming request to the URL ”http://localhost:3001/streaming”. The useStreaming hook handles the streaming request and provides the res, isLoading, and err values to manage the loading and error states.

The component conditionally renders different content based on the state of the streaming request. If the request is still loading, it displays “isLoading: true”. If there’s an error, it displays an error message with the error’s message. If the request is successful (res is not null), it displays the response data (res.data).

You can use the TestUseStreaming component in your application whenever you need to handle streaming requests to receive and process data from a server or API, and it will automatically manage the loading and error states, providing a smooth user experience.

Use Scenario

The useStreaming hook is useful in scenarios where you need to receive data from a server or API using streaming responses in a React component. It allows you to interact with APIs or servers to receive and process data efficiently while maintaining a smooth user experience by displaying loading indicators and handling errors gracefully.