Giter Site home page Giter Site logo

svenkirschbaum / react-stomp-hooks Goto Github PK

View Code? Open in Web Editor NEW
59.0 4.0 12.0 1.43 MB

This repository contain a react library which enables simple access to stomp subscriptions via hooks.

License: MIT License

HTML 1.59% JavaScript 49.51% CSS 1.38% TypeScript 47.52%

react-stomp-hooks's Introduction

react-stomp-hooks

A react library to manage a application wide STOMP connection via SockJS or Websockets.

NPM Build JavaScript Style Guide

Install

npm install --save react-stomp-hooks

Usage

See also the supplied example project, and its sourcecode.

import React from "react";

import { StompSessionProvider, useSubscription } from "react-stomp-hooks";

const App = () => {
  return (
    //Initialize Stomp connection, will use SockJS for http(s) and WebSocket for ws(s)
    //The Connection can be used by all child components via the hooks or hocs.
    <StompSessionProvider
      url={"https://stream.elite12.de/api/sock"}
      //All options supported by @stomp/stompjs can be used here
    >
      <SubscribingComponent />
      <SendingMessages />
    </StompSessionProvider>
  );
};

function SubscribingComponent() {
  const [lastMessage, setLastMessage] = useState("No message received yet");

  //Subscribe to /topic/test, and use handler for all received messages
  //Note that all subscriptions made through the library are automatically removed when their owning component gets unmounted.
  //If the STOMP connection itself is lost they are however restored on reconnect.
  //You can also supply an array as the first parameter, which will subscribe to all destinations in the array
  useSubscription("/topic/test", (message) => setLastMessage(message.body));

  return <div>Last Message: {lastMessage}</div>;
}

export function SendingMessages() {
  //Get Instance of StompClient
  //This is the StompCLient from @stomp/stompjs
  //Note: This will be undefined if the client is currently not connected
  const stompClient = useStompClient();

  const sendMessage = () => {
    if (stompClient) {
      //Send Message
      stompClient.publish({
        destination: "/app/echo",
        body: "Echo 123",
      });
    } else {
      //Handle error
    }
  };

  return <Button onClick={sendMessage}>Send Message</Button>;
}

License

MIT © Sven Kirschbaum

react-stomp-hooks's People

Contributors

svenkirschbaum avatar dependabot[bot] avatar kirkegaard avatar

Stargazers

Tiêu Phong avatar Myagmarsuren  avatar lushevol avatar javi avatar Stevan Borus avatar abolfazl shamsollahi avatar  avatar Ahmet Erdinç Yılmaz avatar jack ning avatar Yann avatar  avatar Lee Kyuho avatar André_Teixeira_1998 avatar  avatar  avatar Lennart Hildebrandt avatar errorstudent avatar Goran Paunović avatar snyung avatar Hidan avatar joshjo-nsuslab avatar Ben Chilcott avatar Anthony S. Wu avatar  avatar Seongjun Hong avatar 玻璃娃娃 avatar twistar avatar Mikhail Lapshin avatar Mark Anderson avatar Muhammed Topgul avatar Murph Finnicum avatar  avatar  avatar simens_green avatar Amir Shariati avatar Arturs Langenfelds avatar Michael Raguse avatar UngKaKu avatar Sean Lau avatar Róbson Machado Rosa avatar Ederson Berti avatar Nik Elin avatar Andrija Pavlovic avatar Fernando Canedo avatar Utku Enes GÜRSEL avatar  avatar Ivan Andika avatar Ilya Shaplyko avatar Maziar Nemati avatar Tiny Storm avatar Roy Paulsen avatar Vasilii avatar  avatar Jeffrey Soriano avatar skaifun avatar Timur avatar cyper avatar Paul Hoenecke avatar  avatar

Watchers

Lucian avatar Roy Paulsen avatar  avatar Goran Paunović avatar

react-stomp-hooks's Issues

No documentation

The example doesn’t show how to send message with the hook.

Please help me

import { useStompClient, useSubscription } from 'react-stomp-hooks'
import { useEffect, useState } from 'react'

import { create_UUID } from '../utils/StringUtils'
import { Button, Typography } from 'antd'
import serializer from '../utils/serializers/serializer'

const uuid: string = create_UUID()

export const Git = ({ content }: any) => {
	return (
		<div style={{ display: 'flex', alignItems: 'center' }}>
			<Typography style={{ color: 'white' }}>
				Github repository created:
			</Typography>
			<Button href='https://github.com/autotests-cloud/AUTO-1150' type='link'>
				{content}
			</Button>
		</div>
	)
}

export const Telegram = ({ content }: any) => {
	return (
		<iframe
			style={{ width: '100%', height: '650px', marginTop: '200px' }}
			id='telegram-post-autotests_cloud-17'
			src={`https://t.me/${content}?embed=1&discussion=1&comments_limit=5&dark=1`}
		></iframe>
	)
}

export const Subscribing = () => {
	const [lastMessage, setLastMessage] = useState<any>()

	useSubscription(`/topic/${uuid}`, (message: any) => {
		setLastMessage(addSocketEvent(message.body))
	})

	const addSocketEvent = (message: any) => {
		console.log(JSON.parse(message))

		const { contentType, content } = JSON.parse(message)

		switch (contentType) {
			case 'git':
				return <Git content={content} />
			case 'notification':
				return <Telegram content={content} />
		}
	}

	return (
		<>
			<div>{lastMessage}</div>
		</>
	)
}```
The lastmessage state removes the component and replaces it with another one, and I want them to alternate one after another.
What to do?




Export StompJS types

I can't seem to import IMessage, I'm assuming other types are missing as well from @stomp/stompjs. Thanks for creating this library!

global is not defined

I'm getting the following error:

image

My source:

import {StompSessionProvider} from "react-stomp-hooks";

// ...

<StompSessionProvider
    url={"https://stream.elite12.de/api/sock"}
    debug={(str) => {
        console.log(str);
    }}>
    <Router>
        <Box sx={{display: 'flex', width: '100%', height: '100%'}}>
            <NavigationBar/>
            <Box
                component="main"
                sx={{
                    flexGrow: 1,
                    p: {md: 3},
                    // width: {sm: `calc(100% - ${drawerWidth}px)`},
                    width: '100%',
                    height: '100%',
                    backgroundColor: (theme: Theme) => theme.palette.mode === 'dark' ? theme.palette.background.paper : '#f5f5f5'
                }}>
                <Toolbar/>
                <PageContainer>
                    <Suspense fallback={<div>Loading...</div>}>
                        <MainPage/>
                    </Suspense>
                </PageContainer>
            </Box>
        </Box>
    </Router>
</StompSessionProvider>

I've tried manually adding the sockjs-client dependency, but it made no difference. Any ideas?

Has anyone experienced this issue with iOS?

My backend is using spring boot and when it sends a message my android phone does receive it when using the website but my iOS phone doesn't receive the same message under the same circumstances

Problem with CORS credentials

Hello. I have a problem with CORS. I configured my spring boot app and allow
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOriginPatterns("*")
.withSockJS();
}
But still receive CORS Error

image

This is how it looks in react
const HomePage = () => {
return (
<StompSessionProvider url={"http://localhost:9000/ws"}>
<TestComp/>
</StompSessionProvider>
)
}
const TestComp = () => {
useSubscription("/2/queue/messages", (message) => console.log(message));
return (
<p></p>
)
}

I also tried to allow strictly one origin, but it didnt help too (

Wrong import from stompJS

After the 2.2.0 update, I got an error using connectHeaders in StompSessionProvider, saying that connectHeaders is not a correct property.
In interface StompSessionProviderProps.d.ts, StompConfig is imported from
import { StompConfig } from '@stomp/stompjs/esm6/stomp-config';
but should be imported from
import { StompConfig } from '@stomp/stompjs';

The example project doesn't run

I pulled the project and tried to the example through the guide provided:
npm install
npm start

This is the result:

> [email protected] start
> node ../node_modules/react-scripts/bin/react-scripts.js start

node:internal/modules/cjs/loader:958
  throw err;
  ^

Error: Cannot find module 'C:\React\workspace\react-stomp-hooks-master\node_modules\react-scripts\bin\react-scripts.js'
    at Module._resolveFilename (node:internal/modules/cjs/loader:955:15)
    at Module._load (node:internal/modules/cjs/loader:803:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:18:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

Node.js v18.8.0

Could you please help?

Handshake have no connectHeaders

Hello ! I pass Authorization header into connectHeaders but handshake request not containing it.

This how my code looks like"
image

console log of THIS

1

But handshake request not containing it
image

Connect few sockets through provider

Hey! How can i add few connections. Because i have 2 sevices and each other have separate websocket connection. Heres 2 urls which i want connect
//
<StompSessionProvider
// url={${BASE_URL()}/users/v1/open/notifications-websocket}
url={${BASE_URL()}/lessons/v1/open/websocket/drawboards}
debug={STOMP => console.log({STOMP})}
connectHeaders={{Authorization: getAuthorizationHeader()}}
onConnect={() => console.log({STOMP_CONNECT: 'TCP connection successfully established'})}
reconnectDelay={1}
>


Multiple rendering

Hey, I have noticed when using redux to manage message state or any redux action within <StompSessionProvider></StompSessionProvider>, stomp is disconnecting and then reconnect when state changes or redux action is executed. Could you check on this. This is not happening when using react useState hook.

parent-component

action

this._stompHandler is undefined when using stomp client on initial load of child component

Hello! Thank you for making this library, made working with stompjs in React much easier.

I have one issue though - I need to use stompClient in a child component when it first loads.
Example code:

const Child = () => {
  // ...
  const stompClient = useStompClient();

  useEffect(() => {
    if (stompClient) {
      // use stomp client to send a message
    }
  }, [stompClient]);

  // ...
};

const App = () => {
  return (
    <StompSessionProvider
      url={"ws://localhost:8080/ws"}
      debug={(str) => console.log(str)}
    >
      <BrowserRouter>
        <Routes>
          <Route path="child/:uri" element={<Child  />} />
        </Routes>
      </BrowserRouter>
    </StompSessionProvider>
  );
};

Doing this throws a Uncaught TypeError: this._stompHandler is undefined error, and I'm not sure how to deal with it.
It appears it is caused by the stompClient existing, but stompClient.connected not being true.

Adding stompClient?.connected inside the dependency array of useEffect and checking for if (stompClient && stompClient.connected) prevents the error, but does not seem to make it re-fire automatically (it only re-fires when I interact with the page).

I also tried appending const [connected, setConnected] to the App component, and adding a onConnect={() => setConnected(true)} property to the StompSessionProvider and using that:

const App = () => {
  const [connected, setConnected] = useState(false);
  return (
    <StompSessionProvider
      url={"ws://localhost:8080/ws"}
      debug={(str) => console.log(str)}
      onConnect={() => setConnected(true)}
    >
      <BrowserRouter>
        <Routes>
          <Route path="child/:uri" element={<Child  />} />
        </Routes>
      </BrowserRouter>
    </StompSessionProvider>
  );
};

Either passing connected down as prop to the child and checking for it inside useEffect, or waiting for it to be true before rendering the BrowserRouter. The results appear to be the exact same.

I'm not sure if I'm doing something dumb here :(

Edit: Forgot to mention, one thing to keep in mind is that if I render App and afterwards navigate to Child by some means (pressing a button or similar) the error isn't thrown. It only seems to happen when I directly load the child route via pasting it in the url bar inside the browser or I press refresh while on it. I assume this works in the first case because the parent has time to connect properly before navigating elsewhere.

need for a custom unsubscribe

besides when "parent component is unmounting" there is situations that you need to unsubscribe a specific destination. i didn't find fancy way to do so with this library.
one clean way, for example, could be returning an array of subscription objects as useSubscription hook output.

or maybe there is a clean way to do it and it just not well documented.
thanks anyway for lib 👍

bug?: useSubscription in testing

I'm having some trouble writing a test leveraging the useSubscription hook. I'm using NextJS w/ Jest & RTL to test the component. Here is the component, when I render the component, wrapped in the StompSessionProviderMock it keeps creating an error, TypeError: Cannot read properties of undefined (reading 'delete') when following the example.

I was able to get it working with jest.mock, but it feels a bit hacky to me,

// imports...

const mockedMessage = jest.fn<IMessage, any, any>();

jest.mock("react-stomp-hooks", () => ({
  ...jest.requireActual("react-stomp-hooks"),
  useSubscription: (_topic: string, callbackFn: (message: IMessage) => void) => {
    if(mockedMessage.mock.calls.length) return;
    callbackFn(mockedMessage());
  },
}));

afterEach(() => {
    stompMock.reset();
    mockedMessage.mockReset();
});

test("should return null when no message received", () => {
  mockedMessage.mockReturnValue({ body: JSON.stringify("") } as IMessage);
  
  const { container } = render(
    <stompMock.StompSessionProviderMock>
      <WebSocketStatus topic="test-topic" />
    </stompMock.StompSessionProviderMock>
  );

  expect(container).toBeEmptyDOMElement();
});

I was using v2.2.1, but I've upgraded to v3.0.0, and the same issue occurs.

Conditional connecting

Is it possible to conditionally connect to server with this library? There is an example with conditional subscription, but StompSessionProvider doesn't have a way to connect manually (for example to request auth token before connection or simply to check if websockets are currently enabled in case they are optional).

Setting url to null or empty string will just set current page url.

StompSessionProvider doesn't apply headers

I am configuring my StompSessionPRovider like so:

      <StompSessionProvider
        url="wss://bla/ws"
        heartbeatIncoming={3000}
        heartbeatOutgoing={0}
        stompVersions={
          new Versions(["1.2"])
        }
        connectHeaders={{
          Authorization: token,
        }}
        debug={(str) => {
          console.log(str);
        }}
      >

The connection fails and when I inspect the request, I can see no heartbeat, no authorization, and no versions. The dev tools also says that "Provisional headers shown." which seems to indicate a problem with the headers. It tries to connect to the correct URL tho, which is passed along with the headers.
Any idea what I am doing wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.