Fissio
Fissio

Reputation: 3758

ReactJS, react-router and socket.io

I'm learning ReactJS, Express and socket.io by making a small application where users can join rooms, and interact with each other inside the room (content NYI). Currently, the idea is to have a RoomList view, and an individual Room view. The number of current users in a room should be visible in the RoomList (Room 1: 2 users, for example).

My router config looks like this:

<Router history={hashHistory}>
    <Route path="/" component={App}>
        <Route path="rooms" component={RoomList}></Route>
        <Route path="rooms/:roomId" component={Room}></Route>
    </Route>
</Router>

And the App component:

export default React.createClass({
  componentDidMount() {
    var socket = io.connect('/')
    socket.on('connect', function(data) {
      socket.emit('message', "Dududu")
      socket.on('message', function(data) {
        console.log("Message:", data);
      })
    })
  },

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    )
  }
})

The problem is, how can I access the socket instance created here in another component? For example, I'd like to add socket events for joining/leaving a room and other room-specific events in the Room component, updating the RoomList's user count in the RoomList component etc. How can I share the socket object globally, or what is the recommended practice for dealing with sockets and multiple components?

Upvotes: 4

Views: 3979

Answers (2)

Josh Lear
Josh Lear

Reputation: 139

Another solution that I just did on my chat app where I could send realtime communication without any rendering.

I just used uuid in the parent components state to create an id that I could pass from the parent to context then access in any child component. At that point I just created a room between whatever components that I wanted to share info with and named it using that uuid.

The reason I went this route rather than Fissio's is because I didn't want to store that huge socket in state.

Now you can have multiple users who each have a unique socket just for them!

Upvotes: 1

Fissio
Fissio

Reputation: 3758

Found out what to do through vigorous googling and github issue searching, in the App component do this.setState({socket: socket}) and then for the view, use React.cloneElement, passing the socket as a prop. Then you can access the socket from child components through this.props.socket.

export default React.createClass({
  componentWillMount() {
    var socket = io.connect('/');
    this.setState({socket: socket});
  },

  render() {
    return (
      <div>
        {
          React.cloneElement(this.props.children, {socket: this.state.socket})
        }
      </div>
    )
  }
})

Upvotes: 3

Related Questions