задача very complex, ) если не знать куда жать...
вот тебе мини прожект:
.babelrc
{
  "presets": [
    "env",
    "react",
    "es2015",
    "stage-0"
  ],
  "plugins": [
    "transform-class-properties"
  ]
}
package.json
{
  "name": "ttttest",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "babel-core": "^6.26.3",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-preset-env": "^1.7.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "express": "^4.16.4",
    "parcel-bundler": "^1.10.3",
    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "react-router": "^4.3.1",
    "react-router-dom": "^4.3.1"
  }
}
server.js
const path = require('path')
const Bundler = require('parcel-bundler')
const bundler = new Bundler(path.join(__dirname, 'src', 'index.html'), {})
const express = require('express')
const app = express()
const server = require('http').Server(app)
// const io = require('socket.io')(server)
const server_messages = [
  { id: 1, title: 'message1' },
  { id: 2, title: 'message2' }
]
app.use(express.static(path.join(__dirname, 'public')))
app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
app.get('/data', function (req, res) {
  setTimeout(() => res.json(server_messages), 5000)
})
// io.on('connection', function (socket) {
// })
app.use(bundler.middleware())
server.listen(2999, () => console.log('started at http://localhost:2999'))
src/index.html
<html>
<head></head>
<body>
  <div id="app"></div>
  <script type="text/javascript" src="index.js"></script>
</body>
</html>
src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import createBrowserHistory from "history/createBrowserHistory";
import { Router, Route, Link } from "react-router-dom"
const browserHistory = createBrowserHistory()
class Index extends React.Component {
  state = {
    loading: false
  }
  render() {
    return <React.Fragment>
      <h2>Home</h2>
      <button onClick={() => {
        this.setState({ loading: true })
        fetch('/data').then(r => r.json()).then(data => this.setState({ data, loading: false }))
      }}>getData</button>
      <button onClick={() => console.log('cancel')}>cancel request</button>
      {this.state.loading && <div>loading...</div>}
      {this.state.data && this.state.data.map(d => <div>{`${d.id} - ${d.title}`}</div>)}
    </React.Fragment>
  }
}
const About = () => <h2>About</h2>
const Users = () => <h2>Users</h2>
ReactDOM.render(
  <Router history={browserHistory}>
    <div>
      <nav>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about/">About</Link>
          </li>
          <li>
            <Link to="/users/">Users</Link>
          </li>
        </ul>
      </nav>
      <Route path="/" exact component={Index} />
      <Route path="/about/" component={About} />
      <Route path="/users/" component={Users} />
    </div>
  </Router>,
  document.getElementById('app')
)
осталось сделать fetch cancelable:
https://developers.google.com/web/up...bortable-fetch
https://stackoverflow.com/questions/...-fetch-request
или использовать 
https://github.com/axios/axios
у него есть cancel
или забить на это и продумать поведение приложения заранее... )