Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect to Laravel Websocket with React?

I'm building an ordering app, where I do the backend with Laravel and the front end with both ReactJS and React Native

I want real-time updates whenever a customer posts an order and whenever an order gets updated.

Currently, I managed to get WebSocket running that uses the pusher API using devmarketer his tutorial.

I'm successful in echoing the order in the console, but now I want to access the channel using my react app

And at this step is where I am facing difficulties.

As I'm unsure how to create a route that is accessible to both my apps and how to access the channel through this route.

The official laravel documentation gives an example of how to access pusher but not how to connect to it with for example an outside connection (example: my react native app)

window.Echo = new Echo({
  broadcaster: 'pusher',
  key: 'rapio1',
  host: 'http://backend.rapio',
  authEndpoint: 'http://backend.rapio/broadcasting/auth',
  auth: {
    headers: {
      // Authorization: `Bearer ${token}`,
      Accept: 'application/json',
    },
  }
  // encrypted: true
});
window.Echo.channel('rapio.1').listen('OrderPushed', (e) =>{
    console.log(e.order)
})

So my question is how can I access a broadcasting channel on my React apps?

ADDED BACKEND EVENT


class OrderPushed implements ShouldBroadcastNow
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $neworder;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Order $neworder)
    {
        $this->neworder = $neworder;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        //return new Channel('Rapio.'.$this->neworder->id);
       return new Channel('Rapio');

    }
    public function broadcastWith()
    {
        return [
            'status' => $this->neworder->status,
            'user' => $this->neworder->user->id,
        ];
    }
}
like image 295
Salman Avatar asked Jun 27 '19 14:06

Salman


2 Answers

Are you using the broadcastAs() method on the backend?

It's important to know this in order to answer your question properly because if you are, the Laravel echo client assumes that the namespace is App\OrderPushed.

When using broadcastAs() you need to prefix it with a dot, to tell echo not to use the namespacing so in your example, it would be:

.listen('.OrderPushed')

Also, you don't need to do any additional setup on the backend in order for each client application to connect to the socket server unless you want to have a multi-tenancy setup whereby different backend applications will make use of the WebSockets server.

I also use wsHost and wsPort instead of just host and port, not sure if that makes a difference though

like image 94
ThatCoderGuy Avatar answered Nov 01 '22 07:11

ThatCoderGuy


If you can access the data on the frontend by simply console.log'ing to the console you should already be most of the way there.

The way you would actually get the data into your react components depends on if you're using a state management library (such as redux) or just pure react.

Basically, you would maintain a local copy of the data on the frontend and then use the Echo events to update that data. For example, you could have a list of orders in either redux, one of your react components, or somewhere else, that you could append to and modify based on creation, update, and deletion events.

I would personally create an OrderCreated, OrderUpdated, and OrderDeleted event on the backend that would contain the given order model.

class OrdersList extends React.Component {
    componentDidMount() {
        this.fetchInitialDataUsingHttp();

        //Set up listeners when the component is being mounted
        window.Echo.channel('rapio.1').listen('OrderCreated', (e) =>{
            this.addNewOrder(e.order);
        }).listen('OrderUpdated', (e) =>{
            this.updateOrder(e.order);
        }).listen('OrderDeleted', (e) =>{
            this.removeOrder(e.order);
        });
    }

    componentWillUnmount() {
        //@TODO: Disconnect echo
    }
}
like image 20
Jonas Lindenskov Nielsen Avatar answered Nov 01 '22 08:11

Jonas Lindenskov Nielsen