iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 20
0

介紹

聊天室都會想到使用 Socket.io來製作,因為有持續監聽與 Server Side 可以主動 PUSH 的特性,一般的網頁方式就要定期去發Request,相對之下Socket.io在聊天室這類應用是比較好的選擇

安裝 socket.io套件

    "isomorphic-unfetch"
    "socket.io"
    "socket.io-client"

Server 起一個 Scoket.io 服務 const io = require('socket.io')(server)
使用io.on 第一個參數建立連線 connection ,第二個參數 監聽 socket 使用 socket.on('message'),
當client端有送出 message event, server 監聽到 client 傳來 message 時就把 data 推到 DB(這邊用一個假的陣列替代),接著使用 socket.broadcast.emit('message', data) 把這筆接收到的 data 再推倒前端 client 如果有建立連線 就會收到server 傳來的 data

server side

 省略...
const io = require('socket.io')(server)

// 假資料庫
const messages = []

// socket.io server
io.on('connection', socket => {
  socket.on('message', (data) => {
    messages.push(data)
    socket.broadcast.emit('message', data)
  })
})

nextApp.prepare().then(() => {
  app.get('/messages', (req, res) => {
    res.json(messages)
  })

 省略...
})

restful部分使用一個 messages 可以 撈到所有的資料

client Side
isomorphic-unfetch 是一個 server 的fetch polyfill 在使用ssr的時候記得補上,SSR先同步所有 Message

import { Component } from 'react'
import io from 'socket.io-client'
import fetch from 'isomorphic-unfetch'

class HomePage extends Component {
  // 同步 SSR 所有目前 Message
  static async getInitialProps ({ req }) {
    const response = await fetch('http://localhost:3000/messages')
    const messages = await response.json()
    return { messages }
  }

  static defaultProps = {
    messages: []
  }

  // 初始化 state
  state = {
    field: '',
    messages: this.props.messages
  }

  // 連結socket並監聽server打來的資訊
  componentDidMount () {
    this.socket = io()
    this.socket.on('message', this.handleMessage)
  }

  // 結束對server的監聽
  componentWillUnmount () {
    this.socket.off('message', this.handleMessage)
    this.socket.close()
  }

  // 如果Server有打回資料就使用 concat 疊加上去
  handleMessage = (message) => {
    this.setState(state => ({ messages: state.messages.concat(message) }))
  }

  handleChange = event => {
    this.setState({ field: event.target.value })
  }

  // 使用form 因為是SPA所以阻止 form表單的 submit (event.preventDefault())
  handleSubmit = event => {
    event.preventDefault()

    // 創建要塞到後端的object
    const message = {
      id: (new Date()).getTime(),
      value: this.state.field
    }

    // 推送到後端
    this.socket.emit('message', message)

    // 使用 concat 疊加到state.message 
    this.setState(state => ({
      field: '',
      messages: state.messages.concat(message)
    }))
  }
 以下省略....
}

export default HomePage

總結

在使用 Next.js 開發 socket.io 只需注意 SSR 部分,初始話部分記得先使用 fetch 同步一下資訊,其他 socket.io開發模式跟一般開發一樣

官方 github範例
https://github.com/zeit/next.js/tree/canary/examples/with-socket.io


上一篇
Next.js & Gh-Pages
下一篇
Next.js & React-GA
系列文
Next.js + 各種套件組合30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言