Stefan Gies
Stefan Gies

Reputation: 318

Redux Saga socket.io

I'm currently developing a chat client which have to be able to receive messages and to send messages. The only problem I'm facing to is that I really don't know how to send messages inside the given component from the Saga example.

I found the example on their API documentation https://redux-saga.js.org/docs/advanced/Channels.html.

Am I be able to reuse the socket const I created inside the watchSocketChannel function? Or do I need to just create the connection twice? What would you advise to do?

import {all, apply, call, fork, put, take} from 'redux-saga/effects'
import {eventChannel} from 'redux-saga';
import * as actions from "../actions";
import io from 'socket.io-client';

function createSocketConnection(url, namespace) {
    return io(url + '/' + namespace);
}

function createSocketChannel(socket) {
    return eventChannel(emit => {
        const eventHandler = (event) => {
            emit(event.payload);
        };

        const errorHandler = (errorEvent) => {
            emit(new Error(errorEvent.reason));
        };

        socket.on('message', eventHandler);
        socket.on('error', errorHandler);

        const unsubscribe = () => {
            socket.off('message', eventHandler);
        };

        return unsubscribe;
    });
}

function* emitResponse(socket) {
    yield apply(socket, socket.emit, ['message received']);
}

function* writeSocket(socket) {
    while (true) {
        const { eventName, payload } = yield take(actions.WEBSOCKET_SEND);
        socket.emit(eventName, payload);
    }
}

function* watchSocketChannel() {
    const socket = yield call(createSocketConnection, 'http://localhost:3000', 'terminal');
    const socketChannel = yield call(createSocketChannel, socket);

    console.log(socket);

    while (true) {
        try {
            const payload = yield take(socketChannel);
            yield put({type: actions.WEBSOCKET_MESSAGE, payload});
            yield fork(emitResponse, socket);
        } catch (err) {
            console.log('socket error: ', err);
        }
    }
}

export default function* root() {
    yield all([
        fork(watchSocketChannel),
    ])

I know that the fork function is attaching the watchSocketChannel function to saga and constantly listening.

Upvotes: 3

Views: 4805

Answers (1)

NoriSte
NoriSte

Reputation: 3709

I'm not sure I have understood correctly your question... If you're asking how/where to fork the writeSocket saga to allow you to dispatch the actions.WEBSOCKET_SEND) action and have your message sent to the socket:

isn't sufficient to do add a fork in the middle of the socket channel creation?

const socket = yield call(createSocketConnection, 'http://localhost:3000', 'terminal');
fork(writeSocket, socket); // I've added this line
const socketChannel = yield call(createSocketChannel, socket);

Upvotes: 2

Related Questions