Code Monkey home page Code Monkey logo

react-actioncable-provider's Introduction

ActionCable Provider for React

This package provides an ActionCable context provider and consumer to allow you to subscribe to ActionCable channels in your React components.

Requirements

As this package uses React's new Context API, React 16.3+ is required.

Install

npm install --save react-actioncable-provider
# OR
yarn add react-actioncable-provider

Usage

The public API exports two components that you'll use: <ActionCableProvider /> and <ActionCableConsumer />.

<ActionCableProvider />

The provider is used in an outer container and wraps all of the components that may or may not consume the context. It accepts one of two props: url and cable. Passing url will result in the provider instantiating its own ActionCable.Consumer with that URL. Passing cable allows you to manually instantiate an ActionCable.Consumer on your own and pass it to the provider to be used by all descendent consumers.

With url

<ActionCableProvider url="ws://test.example.com/cable">...</ActionCableProvider>

With cable

import ActionCable from 'actioncable';

const cable = ActionCable.createConsumer('ws://test.example.com/cable');

<ActionCableProvider cable={cable}>...</ActionCableProvider>;

<ActionCableConsumer />

The consumer will wrap an individual component. It accepts several props:

  • channel [String] Name of the channel to which you want to subscribe.
  • channel [Object] An object with a channel key which denotes the channel to which you want to subscribe. All other keys are passed to the channel as params.
  • onConnected [Function] A handler function that is called when the channel connects.
  • onDisconnected [Function] A handler function that is called when the channel disconnects.
  • onInitialized [Function] A handler function that is called when the ActionCable.Consumer is initialized.
  • onRejected [Function] A handler function that is called when the requested subscription is rejected.
  • onReceived [Function] A handler function that is called when the channel transmits a message to the client.
import React from 'react';
import PropTypes from 'prop-types';
import { ActionCableConsumer } from 'react-actioncable-provider';

export default class Widget extends React.Component {
  static propTypes = {
    message: PropTypes.string
  };

  constructor(...props) {
    super(...props);

    this.handleReceived = this.handleReceived.bind(this);

    this.state = {
      message: ''
    };
  }

  handleReceived(message) {
    this.setState(state => {
      return {
        message
      };
    });
  }

  render() {
    return (
      <ActionCableConsumer
        channel="WidgetChannel"
        onReceived={this.handleReceived}
      >
        <h1>{this.state.message}</h1>
      </ActionCableConsumer>
    );
  }
}

Other Uses

React Native

See https://github.com/cpunion/react-native-actioncable

Server Side Rendering

See #8

Example: https://github.com/cpunion/react-actioncable-ssr-example

react-actioncable-provider's People

Contributors

cpunion avatar horiaradu avatar mgoggin avatar peterrkang 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

react-actioncable-provider's Issues

V2.0.0 error for react version

Hi, is react > 16.3 supported?
This is the error shown for upper versions: error "react-actioncable-provider#react" is wrong version: expected "~16.3.0", got "16.8.1"

Web-socket unsubscribes and doesn't reconnect

I've suffered from an issue that once a message is received and the state changes, triggering a render, it sends an unsubscribe command, followed by a subscribe command. 95% of the time it doesn't reconnect, I'm unsure if this is an asynchronous issue or intended behaviour.

To get around this, I've had to render the ActionCableConsumer just once:

    this.acc || (this.acc = <ActionCableConsumer
             channel='NotificationsChannel'
             onReceived={this.handleReceived}
           />);

Is there a better way of doing this? Or am I missing something?

createConsumer is not a function

In this example in the README:

import { ActionCableProvider } from 'react-actioncable-provider'
const cable = ActionCable.createConsumer('ws://localhost:3000/cable')

export default function Container (props) {
    return (
        <ActionCableProvider cable={cable}>
            <MyApp />
        </ActionCableProvider>
    )
}

Where does ActionCable come from? I tried importing it, but it's a component.

Passing headers while establishing the contact

Could anyone explain that how we can pass the auth-token in ActionCableProvider in order to authenticate the user in the backend rails app.
One way is to pass the auth-token in the URL string. But it is not a secure method. The auth token can be seen easily in the logs at the backend.

How to check there is a connection?

Hi,

I want to check if there is a connection. This is necessary for my app because users keep their apps on background and when app is in foreground I want to make sure there is a connection.

So how can I check there is a connection? How to keep app connected?

Thank you.

onReceived is never called

What I'm trying to do?

I'm trying to use the backend with some background jobs to notify user about the "processing" time of some CSV file. For that, I'm notifying the frontend about the processed rows of the file, but, onReceived function is never called. What I'm doing wrong?

Backend

(this is working, tested manually)

# frozen_string_literal: true

class ImportedBatchChannel < ApplicationCable::Channel
  def subscribed
    stream_for ImportedBatch.find(params[:room])
  end

  def receive(data)
    puts '*****************************'
    puts data
    puts '*****************************'
  end
end

Frontend

(this is not working, OnReceived is never called)

App.js (REACT_APP_WS_URL is localhost:3001/cable for development)

<ActionCableProvider url={process.env.REACT_APP_WS_URL}>
  <MuiThemeProvider theme={theme}>
    <CssBaseline />
    <Navbar />
    <Router />
    <Footer />
  </MuiThemeProvider>
</ActionCableProvider>

ProgressBar.js

import React, { Component, Fragment } from 'react'
import { ActionCable } from 'react-actioncable-provider'
import LinearProgress from '@material-ui/core/LinearProgress'

export default class extends Component {
  state = {
    total: this.props.total,
    processed: this.props.processed,
  }

  onReceived(data) {
    console.log('Recebi', data)
    this.setState({
      total: data.totalRows,
      processed: data.processedRows,
    })
  }

  sendMessage = () => {
    this.refs.ImportedBatchChannel.perform('receive', { message: 'olha essa mensagem' })
  }

  render() {
    return (
      <Fragment>
        <ActionCable
          ref={'ImportedBatchChannel'}
          channel={{
            channel: 'ImportedBatchChannel',
            room: this.props.batchId,
          }}
          onReceived={this.onReceived}
        />

        <div className={this.props.classes.progressBar}>
          <LinearProgress
            variant="determinate"
            value={(this.state.processed / this.state.total) * 100}
          />
        </div>
        <button onClick={this.sendMessage}>Mandar Mensagem</button>
      </Fragment>
    )
  }
}

URL can't update accordingly

Url is dynamic in my project. when url changes, we found action cable can't update accordingly. So I found the problem is we should use the next props but not this props as an argument for componentWillMount in componentWillReceiveProps(https://github.com/cpunion/react-actioncable-provider/blob/master/lib/index.js#L41); Below is my code for reference:

componentWillMount: function () {
   this.connect(this.props);
},

componentWillUnmount: function () {
   if (!this.props.cable && this.cable) {
     this.cable.disconnect()
   }
 },

connect:  function (props) {
   console.log("action cable url on provider ============>", props.url)
   if (props.cable) {
     this.cable = props.cable
   } else {
     this.cable = actioncable.createConsumer(props.url)
   }
 },

 componentWillReceiveProps: function (nextProps) {
   // Props not changed
   if (this.props.cable === nextProps.cable &&
       this.props.url === nextProps.url) {
     return
   }
   // cable is created by self, disconnect it
   this.componentWillUnmount()
   // create or assign cable
   this.connect(nextProps)
 },

Use Perform in OnConnected

Hi,
I can't seem to work this out but I'd like to use the perform function or this.cable.perform in the onConnected call.
Any help with this would be highly appreciated.
Thanks

Isomorphic app support

Anyone had success using the provider on Isomorphic app?
I'm getting window is not defined error on the server side rendering

WebSocket: window.WebSocket,
                   ^
ReferenceError: window is not defined

New context API

React v16.3 introduces a new context API that replaces the original context API used in this package.

Could you implement this new context API?
If not, this package will not work with React v17.

Warning during yarn install - [email protected]: core-js@<3 is no longer maintained - Upgrade required

Hi, did a fresh yarn install build of my package.json today.

This warning was shown:

warning react-actioncable-provider > react > fbjs > [email protected]: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.

My react version and react-actionable-provider version:

    "react": "16.13.1",
    "react-actioncable-provider": "^2.0.0",

I'm a newbie to this, so if you have any other questions please let me know and I will do my best to help.

document is not defined on React Native

Hello im currently working on a React Native application and i'm getting this error.

Captura de pantalla 2019-03-23 a la(s) 23 12 59

I already try

import ActionCable from 'actioncable';
const cable = ActionCable.createConsumer('ws://test.example.com/cable');
<ActionCableProvider cable={cable}>...</ActionCableProvider>;

like the documentation says https://github.com/cpunion/react-native-actioncable#use-with-react-actioncable-provider but i still getting the same error.

I'm currently using react-native-actioncable but likes the documentation says, is now unmaintained

channel disconnects and reconnects

I'm having the same issue that has been previously reported but I was unable to fix..
I'm working on an app with chat feature and when the component is mounted, the channel is disconnected and reconnects(aparently).. the same happens with every key stroke while writing a message. On the terminal, everything is working fine, except for the messages informing of the channel being unsubscribed and again subscribed.
The problem is intermitent as sometimes I receive the broadcasted data from the server, and other times nothing comes through.

//request.js
import { ActionCableProvider } from 'react-actioncable-provider';
import ActionCable from 'actioncable';
const cable = ActionCable.createConsumer("ws://localhost:3001/cable");

<ActionCableProvider cable={cable}>
    <Chat request_id={this.props.request.id} selected={this.state.selected} sender_id={this.props.user_id} recipient_id={this.props.request.user_id}/>`
</ActionCableProvider>
//chat.js
<ActionCableConsumer
    channel={{channel: "ConversationsChannel",
		        	  conversation: this.state.conversation_id}}
    onReceived={this.handleReceived}
    onDisconnected={console.log("off")}
    onConnected={console.log("on")}
/>

full code @this repository

Any help will be extremly appreciated!

Broadcasted message from Rails ActionCable get lost sometimes

Hi. My backend app, Ruby on Rails, is broadcasting messages properly, however, some of them get lost then my React app, which uses React-ActionCableProdiver, doesn't get those lost ones. I noticed that it happens more frequently in my app in production, which has greater number of transactions in general. I was wondering how I could debug ReactActionCableProvider component in a way that I could monitor this flow then identify where the messages are getting lost, if this is my backend ActionCable or the React ActionCableProvider component.

Thank you so much

React Deprecation Warnings

Started getting a couple of deprecation warnings related to this library with a recent version of React:

Warning: componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details.

* Move code with side effects to componentDidMount, and set initial state in the constructor.
* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.

Please update the following components: ActionCableProvider
Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details.

* Move data fetching code or side effects to componentDidUpdate.
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state
* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.

Please update the following components: ActionCableProvider

Declare Consumer Cable inside Component Lifecycle Method

I need to pass URL parameter for createConsumer to authenticate myself such as :
ws://10.67.1.175:3000/cable?access-token=atokenhere&client=someclientcode&uid=thisisauid.

These infos are in my AsyncStorage (Using expo), so i think i can only retrieve these infos in my React-native component lifecycle method.

So i'm not able to declare my consumer as global var such as :
const cable = RNActionCable.createConsumer("ws://10.67.1.175:3000/cable");

How can i include my createConsumer consumer call in my React Native Class Component.

Deployment fails because of dependency

When I try deploying an app bootstrapped with create-react-app and your dependency, deployment fails with the following error:

remote: Module not found: Error: Can't resolve 'create-react-class' in '/tmp/build_97a69fac11256a030f21ad2eeb0d2cef/node_modules/react-actioncable-provider'

Components show as <Unknown ... /> in React DevTools

ActionCableProvider and ActionCable components show as <Unknown /> in React DevTools which can make debugging difficult.

Since the components are defined in ES5 and not JSX, their displayName property must be set explicitly.

Solved with PR #3

You may need an appropriate loader to handle this file type.

I am getting this error:

ERROR in ./node_modules/react-actioncable-provider/lib/index.js
Module parse failed: Unexpected token (147:12)
You may need an appropriate loader to handle this file type.
|           {
|             cable,
|             ...this.props,
|             ref: this.props.forwardedRef
|           },
 @ ./app/javascript/components/pages/Home/Home.js 11:0-61
 @ ./app/javascript/components ^\.\/.*$
 @ ./app/javascript/packs/application.js
 @ multi (webpack)-dev-server/client?http://localhost:3035 ./app/javascript/packs/application.js

TypeError: Cannot read property 'cable' of undefined

We are getting the following error sporadically:

TypeError: Cannot read property 'cable' of undefined

This is how we use the ActionCableProvider

import ActionCable from "actioncable"
import { ActionCableProvider } from "react-actioncable-provider"

const Provider = props => {
       const cable = ActionCable.createConsumer(
      `${baseURL}?uid=${uid}&access-token=${accessToken}&client=${client}`
    )
    return <ActionCableProvider cable={cable}>{children}</ActionCableProvider>
}

We import the provider and use it like this in the entry point of our App:

import CableProvider from "./ActionCable/ActionCableProvider"

class App extends Component {
  render = () => (
    <div style={{ height: "100%" }}>
      <CableProvider>
        <Switch>
          <Route path="/sign-in" component={myCompnent} />
           ...
          </Switch>
      </CableProvider>
    </div>
  )
}

export default App

React version : 16.8.6
react-actioncable-provider : 2.0.0
actioncable: 5.2.3

We tried passing undefined to the ActionCableProvider just to trigger the exception, but we were unable to reproduce it.

Can someone please shed some light on why this might be happening?
Thanks!

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.