GithubHelp home page GithubHelp logo

mfrachet / server-push-hooks Goto Github PK

View Code? Open in Web Editor NEW
197.0 6.0 26.0 1.93 MB

๐Ÿ”ฅ React hooks for Socket.io, SSE, WebSockets and more to come

Home Page: https://codesandbox.io/s/y091y50plz

License: MIT License

JavaScript 72.19% HTML 0.69% TypeScript 27.12%
hooks socketio react sse server-sent-events

server-push-hooks's Introduction

Build Status

React hooks for handling server-push technologies:

Running samples

To run samples locally, you can:

$ git clone https://github.com/mfrachet/server-push-hooks
$ cd server-push-hooks
$ npm install # install lerna and dependencies at the root
$ npm run bootstrap # install lerna packages dependencies
$ npm run build # build the lerna packages
$ npm start # start the web application
$ npm start:test-server # start the backend services in another terminal
$ npm run e2e # run E2E tests of the projects in another terminal

server-push-hooks's People

Contributors

khaled-hamam avatar niemisami avatar shahoob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

server-push-hooks's Issues

Reduce unneeded code

const callbackRef = useRef(callback);

callbackRef.current = callback;

const socketHandlerRef = useRef(function() {
  if (callbackRef.current) {
    callbackRef.current.apply(this, arguments);
  }
});

Can be simplified to just

const socketHandlerRef = useRef(function() {
  if (callback) {
    callback.apply(this, arguments);
  }
});

Unless there's something that I'm missing? I'm pretty sure the callback doesn't need to be stored.

Support namespaces

Hi, I have two different namespaces that I have to connect and I can see that you don't support namespaces right now. Is there any chance you can add this soon? If you can't, I can submit a pull request to add this feature

Missing prop 'children' in type of SocketIOProvider

I set up the socket.io hook according to the docs and get a type error on the SocketIOProvider:

Type '{ children: Element; url: string; }' is not assignable to type 'IntrinsicAttributes & ISocketIOProviderProps'.
  Property 'children' does not exist on type 'IntrinsicAttributes & ISocketIOProviderProps'.

The SocketIOProvider is supposed to wrap other JSX elements in _app.tsx, so it should accept the 'children' property, but it doesn't. Obviously TypeScript complains about it.

16.7.0-alpha.2 warning

Trying out react "react": "^16.7.0-alpha.2".

This project is currently on alpha.0.

https://github.com/mfrachet/use-socketio/blob/master/package.json#L36

I think these empty array literals as the second argument of useEffect are deprecated.

https://github.com/mfrachet/use-socketio/blob/d156cd954db952998f4bb3747f71df40bb58e5f3/src/useSocket.js#L9

https://github.com/mfrachet/use-socketio/blob/1fcd3d839fd0e3247c0dcd644d364275738e4a94/README.md#L25

https://github.com/mfrachet/use-socketio/blob/1fcd3d839fd0e3247c0dcd644d364275738e4a94/example/src/components/Feed.js#L21

The result in this warning:

react-dom.development.js:506 Warning: useEffect function must return a cleanup function or nothing.
    in Router (created by App)
    in r (created by App)
    in App
warningWithoutStack @ react-dom.development.js:506
commitHookEffectList @ react-dom.development.js:16041
commitPassiveHookEffects @ react-dom.development.js:16055
callCallback @ react-dom.development.js:149
...

I think the clean up function protocol may have changed?

https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1

Edit: I see that they are memoized callbacks, so nevermind!.

Version 2.0.1 is missing the check for window object in provider js file

I'm using the library with next.js as a server side rendering framework, and I found that there was unintended behavior happens as the socket is created in server side although it shouldn't due to this line:

// src/io/provider.ts
if (!window) {
  return <>{children}</>;
}

I found that the built js file didn't have this check, so I cloned the project, and run a build, and somehow that was the only line that didn't make it in the previous build (also package-lock version is on 1.0.1 if this matters).

Before Build (current state)

// lib/io/provider.js
var url = _a.url, opts = _a.opts, children = _a.children;
var socketRef = react_1.useRef();

After Build

var url = _a.url, opts = _a.opts, children = _a.children;
if (!window) {
  return react_1["default"].createElement(react_1["default"].Fragment, null, children);
}
var socketRef = react_1.useRef();

Clarification on Readme Example

In the readme example, you have this line:

const { data: lastMessage, socket, subscribe, unsubscribe } = useLastMessage( "tweet" );

I would like to know if "data: " is necessary when I use the library, or if that is just specific to the connection with twitter

Also, could you please provide examples of how one may use "socket", "subscribe", and "unsubscribe" in the code?

Status information, hooking into connection

Hi,

for a React application, it's useful to display the progress of various things. Socket.io connection, authorization etc. are part of those things, IMO.

With the <SocketIOProvider> approach, I can't seem to find a way to hook into the connection process, and to display "Loading..." messages based on whether or not I'm connected, and to conditionally display components that depend on WebSocket connection, only if the connection is actually established.

I also cannot find a way to attach debug information to the connection.

Currently, I am connecting to my Socket.IO server 3 times with this hook, and I'd like to debug that, but can't see an option to.

What would your advice be?

Thanks!

Feature Request: Provide a way to delay the subscription

Current behavior:

Currently, as soon as the component is mounted, the hook subscribes to receive events.

Proposal:

Add a way to manually enable the subscription when you want. Example:

import { useLazySocket } from 'use-socketio'

function Component(props) {
  const { subscribe, isListening } = useLazySocket('tweet', (newTweet) => {
    // ...
  })

  return <>
    <div>Is enabled: {isListening ? 'yes' : 'no'}</div>
    <button onClick={subscribe}>See new tweets</button>
  </>
}

I was inspired by the Apollo hooks api to make this draft.

Use case examples:

  • Wait for some information required in callback function be returned from server or external service.
  • Wait for a specific state in redux.
  • The component may receive events but for some reason (bad internet connection, mobile device or user not logged in) you don't want to enable it.

Additional socket.io connection when provider is re-rendered

It seems that whenever a component containing the SocketIOProvider is re-rendered, a new socket.io connection is created. I think it has to do with the useRef having a function call as its initial value. Even if the ref value isn't being reset on the re-render, the initialization function is still being called (which creates a new connection). Is this the intended behavior? I guess moving all of our providers way up near the base of the tree would avoid most of the re-renders, but that's not really ideal.

Feature Request: Provide a way to manually unsubscribe

Current behavior:

Currently, the only way to unsubscribe from an event is unmount the component.

Proposal:

Return a function from useSocket hook that, when called, cancels the subscription. Example:

import { useSocket } from 'use-socketio'

function Component(props) {
  const { unsubscribe } = useSocket('tweet', (newTweet) => {
    // ...
  })

  return <button onClick={unsubscribe}>Stop showing tweets</button>
}

In this draft, I suggested that the hook return an object to be similar to the new hook described in #15 but this will be a breaking change.

Use case examples:

  • User has logged out but the component can still be mounted without receiving new updates.
  • A modal dialog has entered in front of the component and you don't want to receive new events because user is not paying attention anymore.
  • User explicitly demonstrated that he doesn't want to receive new updates.

sse-server a bug

in your sse-server.js line9
setTimeout is not very fit here, I suggest you shold use setInterval

your old code

  setTimeout(() => {
    const secondData = { name: "Laetitia" };

    res.write(`data: ${JSON.stringify(secondData)}`);
    res.write("\n\n");
  }, 500);

i suggest

  setInterval(() => {
    const secondData = { name: "Laetitia" };

    res.write(`data: ${JSON.stringify(secondData)}`);
    res.write("\n\n");
  }, 500);

You are using `useEffect` in a wrong way

Hey,

I was curious how your hook works and saw that you are using useEffect in a very inefficient way:

https://github.com/mfrachet/use-socketio/blob/52dc91b93ff6d4a73e11583fd439d0c2e56037a9/src/useSocket.js#L7-L13

Use effect has two parameters - the callback and the reasons to execute the effect again.
As you didn't specify any reasons it will execute the effect on every render of the component which is using your hook.

See https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects for details.

So your code could be improved like this:

const callbackRef = useRef(callback);
callbackRef.current = callback;

useEffect(() => {
    if (eventKey) {
      function socketHandler() {
         callbackRef.current && callbackRef.current.apply(this, arguments);
      }
      socket.on(eventKey, socketHandler);
      return () => socket.removeListener(eventKey, socketHandler);
    }
}, ['eventKey']);

That way socket.on and socket.removeListener are only called if the components mounts/unmounts or eventKey changes

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.