mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
with-socket.io Example updated with _app.js (#4644)
with-socket.io example was using a single index file and was managing connection in there. This would lead handling connection (disconnecting and reconnecting) in each added page. I updated example with addition of `_app.js` and handled connection in there. This helped only subscribing to event in page and maintaining connection throughout example.
This commit is contained in:
parent
f4af03b9c8
commit
6ed2da4575
39
examples/with-socket.io/pages/_app.js
Normal file
39
examples/with-socket.io/pages/_app.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
import App, {Container} from 'next/app'
|
||||
import React from 'react'
|
||||
import io from 'socket.io-client'
|
||||
|
||||
class MyApp extends App {
|
||||
static async getInitialProps ({ Component, ctx }) {
|
||||
let pageProps = {}
|
||||
|
||||
if (Component.getInitialProps) {
|
||||
pageProps = await Component.getInitialProps(ctx)
|
||||
}
|
||||
|
||||
return { pageProps }
|
||||
}
|
||||
state = {
|
||||
socket: null
|
||||
}
|
||||
componentDidMount () {
|
||||
// connect to WS server and listen event
|
||||
const socket = io()
|
||||
this.setState({ socket })
|
||||
}
|
||||
|
||||
// close socket connection
|
||||
componentWillUnmount () {
|
||||
this.state.socket.close()
|
||||
}
|
||||
|
||||
render () {
|
||||
const {Component, pageProps} = this.props
|
||||
return (
|
||||
<Container>
|
||||
<Component {...pageProps} socket={this.state.socket} />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyApp
|
113
examples/with-socket.io/pages/clone.js
Normal file
113
examples/with-socket.io/pages/clone.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
import { Component } from 'react'
|
||||
import Link from 'next/link'
|
||||
import fetch from 'isomorphic-unfetch'
|
||||
|
||||
class ChatTwo extends Component {
|
||||
// fetch old messages data from the server
|
||||
static async getInitialProps ({ req }) {
|
||||
const response = await fetch('http://localhost:3000/messages/chat2')
|
||||
const messages = await response.json()
|
||||
return { messages }
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
messages: []
|
||||
}
|
||||
|
||||
// init state with the prefetched messages
|
||||
state = {
|
||||
field: '',
|
||||
newMessage: 0,
|
||||
messages: this.props.messages,
|
||||
subscribe: false,
|
||||
subscribed: false
|
||||
}
|
||||
|
||||
subscribe = () => {
|
||||
if (this.state.subscribe && !this.state.subscribed) {
|
||||
// connect to WS server and listen event
|
||||
this.props.socket.on('message.chat2', this.handleMessage)
|
||||
this.props.socket.on('message.chat1', this.handleOtherMessage)
|
||||
this.setState({ subscribed: true })
|
||||
}
|
||||
}
|
||||
componentDidMount () {
|
||||
this.subscribe()
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this.subscribe()
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps (props, state) {
|
||||
if (props.socket && !state.subscribe) return { subscribe: true }
|
||||
return null
|
||||
}
|
||||
|
||||
// close socket connection
|
||||
componentWillUnmount () {
|
||||
this.props.socket.off('message.chat1', this.handleOtherMessage)
|
||||
this.props.socket.off('message.chat2', this.handleMessage)
|
||||
}
|
||||
|
||||
// add messages from server to the state
|
||||
handleMessage = (message) => {
|
||||
this.setState(state => ({ messages: state.messages.concat(message) }))
|
||||
}
|
||||
|
||||
handleOtherMessage = () => {
|
||||
this.setState((prevState) => ({ newMessage: (prevState.newMessage + 1) }))
|
||||
}
|
||||
|
||||
handleChange = event => {
|
||||
this.setState({ field: event.target.value })
|
||||
}
|
||||
|
||||
// send messages to server and add them to the state
|
||||
handleSubmit = event => {
|
||||
event.preventDefault()
|
||||
|
||||
// create message object
|
||||
const message = {
|
||||
id: (new Date()).getTime(),
|
||||
value: this.state.field
|
||||
}
|
||||
|
||||
// send object to WS server
|
||||
this.props.socket.emit('message.chat2', message)
|
||||
|
||||
// add it to state and clean current input value
|
||||
this.setState(state => ({
|
||||
field: '',
|
||||
messages: state.messages.concat(message)
|
||||
}))
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<main>
|
||||
<div>
|
||||
<Link href={'/'}><a>{`Chat One ${this.state.newMessage > 0 ? `( ${this.state.newMessage} new message )` : ''}`}</a></Link>
|
||||
<br />
|
||||
<Link href={'/clone'}><a>{'Chat Two'}</a></Link>
|
||||
<ul>
|
||||
{this.state.messages.map(message =>
|
||||
<li key={message.id}>{message.value}</li>
|
||||
)}
|
||||
</ul>
|
||||
<form onSubmit={(e) => this.handleSubmit(e)}>
|
||||
<input
|
||||
onChange={this.handleChange}
|
||||
type='text'
|
||||
placeholder='Hello world!'
|
||||
value={this.state.field}
|
||||
/>
|
||||
<button>Send</button>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ChatTwo
|
|
@ -1,11 +1,11 @@
|
|||
import { Component } from 'react'
|
||||
import io from 'socket.io-client'
|
||||
import Link from 'next/link'
|
||||
import fetch from 'isomorphic-unfetch'
|
||||
|
||||
class HomePage extends Component {
|
||||
class ChatOne extends Component {
|
||||
// fetch old messages data from the server
|
||||
static async getInitialProps ({ req }) {
|
||||
const response = await fetch('http://localhost:3000/messages')
|
||||
const response = await fetch('http://localhost:3000/messages/chat1')
|
||||
const messages = await response.json()
|
||||
return { messages }
|
||||
}
|
||||
|
@ -17,19 +17,37 @@ class HomePage extends Component {
|
|||
// init state with the prefetched messages
|
||||
state = {
|
||||
field: '',
|
||||
messages: this.props.messages
|
||||
newMessage: 0,
|
||||
messages: this.props.messages,
|
||||
subscribe: false,
|
||||
subscribed: false
|
||||
}
|
||||
|
||||
subscribe = () => {
|
||||
if (this.state.subscribe && !this.state.subscribed) {
|
||||
// connect to WS server and listen event
|
||||
this.props.socket.on('message.chat1', this.handleMessage)
|
||||
this.props.socket.on('message.chat2', this.handleOtherMessage)
|
||||
this.setState({ subscribed: true })
|
||||
}
|
||||
}
|
||||
componentDidMount () {
|
||||
this.socket = io()
|
||||
this.socket.on('message', this.handleMessage)
|
||||
this.subscribe()
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this.subscribe()
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps (props, state) {
|
||||
if (props.socket && !state.subscribe) return { subscribe: true }
|
||||
return null
|
||||
}
|
||||
|
||||
// close socket connection
|
||||
componentWillUnmount () {
|
||||
this.socket.off('message', this.handleMessage)
|
||||
this.socket.close()
|
||||
this.props.socket.off('message.chat1', this.handleMessage)
|
||||
this.props.socket.off('message.chat2', this.handleOtherMessage)
|
||||
}
|
||||
|
||||
// add messages from server to the state
|
||||
|
@ -37,6 +55,10 @@ class HomePage extends Component {
|
|||
this.setState(state => ({ messages: state.messages.concat(message) }))
|
||||
}
|
||||
|
||||
handleOtherMessage = () => {
|
||||
this.setState((prevState) => ({ newMessage: (prevState.newMessage + 1) }))
|
||||
}
|
||||
|
||||
handleChange = event => {
|
||||
this.setState({ field: event.target.value })
|
||||
}
|
||||
|
@ -52,7 +74,7 @@ class HomePage extends Component {
|
|||
}
|
||||
|
||||
// send object to WS server
|
||||
this.socket.emit('message', message)
|
||||
this.props.socket.emit('message.chat1', message)
|
||||
|
||||
// add it to state and clean current input value
|
||||
this.setState(state => ({
|
||||
|
@ -65,12 +87,15 @@ class HomePage extends Component {
|
|||
return (
|
||||
<main>
|
||||
<div>
|
||||
<Link href={'/'}><a>{'Chat One'}</a></Link>
|
||||
<br />
|
||||
<Link href={'/clone'}><a>{`Chat Two ${this.state.newMessage > 0 ? `( ${this.state.newMessage} new message )` : ''}`}</a></Link>
|
||||
<ul>
|
||||
{this.state.messages.map(message =>
|
||||
<li key={message.id}>{message.value}</li>
|
||||
)}
|
||||
</ul>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<form onSubmit={(e) => this.handleSubmit(e)}>
|
||||
<input
|
||||
onChange={this.handleChange}
|
||||
type='text'
|
||||
|
@ -85,4 +110,4 @@ class HomePage extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default HomePage
|
||||
export default ChatOne
|
||||
|
|
|
@ -9,19 +9,26 @@ const nextApp = next({ dev })
|
|||
const nextHandler = nextApp.getRequestHandler()
|
||||
|
||||
// fake DB
|
||||
const messages = []
|
||||
const messages = {
|
||||
chat1: [],
|
||||
chat2: []
|
||||
}
|
||||
|
||||
// socket.io server
|
||||
io.on('connection', socket => {
|
||||
socket.on('message', (data) => {
|
||||
messages.push(data)
|
||||
socket.broadcast.emit('message', data)
|
||||
socket.on('message.chat1', (data) => {
|
||||
messages['chat1'].push(data)
|
||||
socket.broadcast.emit('message.chat1', data)
|
||||
})
|
||||
socket.on('message.chat2', (data) => {
|
||||
messages['chat2'].push(data)
|
||||
socket.broadcast.emit('message.chat2', data)
|
||||
})
|
||||
})
|
||||
|
||||
nextApp.prepare().then(() => {
|
||||
app.get('/messages', (req, res) => {
|
||||
res.json(messages)
|
||||
app.get('/messages/:chat', (req, res) => {
|
||||
res.json(messages[req.params.chat])
|
||||
})
|
||||
|
||||
app.get('*', (req, res) => {
|
||||
|
|
Loading…
Reference in a new issue