0

Situation:

I am building a web service using Reactjs and Flummox that will connect to a simple socket server using Socket.io. It will need to keep track of multiple connections per user on their dashboard and am wondering about the best way of doing this. Each user can have multiple tokens, each of which will be associated with a socket connection. I have 2 approaches to this and would like to know which method is more fluxy or if there is another better way that is more fluxy.

My first solution

Creating a class that I import into my react view that handles the socket connections and updates my store when the socket responds. The class might look something like this:

import Flux from '../flux'
import io from 'socket.io-client'

export default class Socket {

    constructor() {

        this.socket = null;
        this.token = null
    }

    connect = (token) => {
        this.token = token;
        this.socket = io('http//192.168.0.144:3000');
        this.listen()
    };

    listen = () => {
        this.socket.on('connect', this.socket.emit('auth', this.token));
        this.socket.on('state', this.stateChanged)
    };

    stateChanged(state) {

        Flux.getActions('sockets').updateState(state, this.token);
    }
}

and from my react view:

import React from 'react'
import Flux from '../flux'
import Socket from './SocketClass'

let _ = React.createFactory;
let div = _('div');
let h1 = _('h1');

export default
class Dashboard extends React.Component {

    constructor() {

        super();

        this.state = {
            tokens: []
        }
    }

    componentWillMount() {

        Flux.getStore('users').on('change', this._storeUpdated);
        Flux.getActions('users').update();
    }

    render() {

        let connections = Flux.getStore('sockets').getStates().forEach(state => {
            h1({},
                state
            )
        });

        return div({},
            connections
        )
    }

    _storeUpdated = () => {

        let tokens = [];
        Flux.getStore('users').getTokens().forEach((token, index) => {
            tokens.push({
                token: token,
                socket: new Socket()
            });
            tokens[index].socket.connect(token)
        });
        this.setState(tokens)
    };
}

Note: This code is just to get the idea across and has not been tested.

My second solution

My second approach would be to do something similar, but instead instantiating a new class for each socket, I could handle the sockets in a single flux store. Something like this:

import { Store } from 'flummox'
import io from 'socket.io-client'

export default
class Socket extends Store {

    constructor(flux) {


        super();

        this.state = {
            sockets: []
        }
    }

    connect(token) {

        let sockets = this.state.sockets;
        sockets.push({
            token: token,
            socket: io('http://192.168.0.144:3000'),
            state: null
        });
        this.state.sockets.forEach((socket, index) => {
            if (socket.token == token) {
                socket.on('connect', socket.socket.emit('auth', socket.token));
                socket.on('state', state => {
                    let sockets = this.state.sockets;
                    sockets[index].state = state;
                    this.setState({sockets: sockets})
                })
            }
        })
    }

    getStates() {
        return this.state.sockets
    }
}
Julien Vincent
  • 1,210
  • 3
  • 17
  • 40
  • I dont think the store should have logic other then updating itself. I believe the first option is the correct way to use it. Same as calling a server API, you shouldnt do it in the store but in an action, and if complex, in an external class. – Kinnza Jul 16 '15 at 15:20
  • So it's better to avoid complex actions? Is there any clear line between what makes an action complex or is it open to interpretation? – Julien Vincent Jul 16 '15 at 15:26
  • Its pretty open, but all the implementations and guidelines i saw (and use) leave the store simple (just holds data and doing nothing much), and the action does the login to access the server and such. Again, i would implement in the action, but will logically split it into a different class that the action will use. – Kinnza Jul 18 '15 at 17:10
  • Alright this makes sense. Maybe put what you said into an answer so I can accept. – Julien Vincent Jul 18 '15 at 17:21

1 Answers1

0

Its pretty open, but all the implementations and guidelines i saw (and use) leave the store simple (just holds data and doing nothing much), and the action does the login to access the server and such. Again, i would implement in the action, but will logically split it into a different class that the action will use.

Kinnza
  • 1,241
  • 10
  • 13