react-router 4 not re-render when clicking <Link>

Viewed 646

I'm working on server-side rendering, so far the initial page can be rendered with react-router successfully according to the path entered to the browser e.g. /, /customers

Code

Routes.jsx

import React from 'react'
import { Route, Switch } from 'react-router-dom'

import Home from './Home'
import CustomerList from './CustomerList'

const PageNotFound = () => <div className="box">
    <h3 className="title">Page Not Found</h3>
</div>

export default () => {
    return <div>
        <Switch>
            <Route exact path="/" component={ Home } />
            <Route path="/customers" component={ CustomerList } />
            <Route component={ PageNotFound }></Route>
        </Switch>
    </div>
}

NavBar.jsx

import React from 'react'
import { Link } from 'react-router-dom'

export default () => <nav className="nav">
    <div className="nav-right">
        <Link to="/" className="nav-item is-tab">Home</Link>
        <Link to="/customers" className="nav-item is-tab">Customer</Link>
    </div>
</nav>

Problem

I'm only successful with server-side rendering, but I cannot get re-render with the client version, when clicking on any of the links there is no re-rendering happens (only the URL gets changed on the browser)

So I have tried with below coding

Routes.jsx

const renderCustomerList = () => {
    console.log('OK')

    return <CustomerList />
}
...

<Route path="/customers" render={ renderCustomerList } />

I still cannot see the log on the client version

I believe I have done with the same coding as the client-side only version (no problems on the client-side only version), so please guide how to solve the problem

Thanks all

1 Answers

I encounter problems with the same symptom, but may not be the same cause since your index.js is not provided here. I hope you have already solved your problem so I just put my findings here for others references.

Go check your root render function in your index.js for both client-side and server-side rendering, mine is as follows with redux:

// React 16 global polyfill for IE < 11
import 'core-js/es6/map'
import 'core-js/es6/set'

import * as React from 'react'
import ReactDom from 'react-dom'
import { Provider, connect } from 'react-redux'
import { BrowserRouter as Router } from 'react-router-dom'

import store from '~/store'
import App from './App'

const mapStateToProps = (state) => ({...state})
const mapDispatchToProps = {}

const render = App => {
  const Connect = connect(mapStateToProps, mapDispatchToProps)(App)

  ReactDom.hydrate(
    <Provider store={store}>
      <Router>
        <Connect />
      </Router>
    </Provider>,
    document.getElementById('root')
  )
}

render(App)

My solution is simply to use <App /> instead of <Connect />, connect store inside children Components.

<Provider store={store}>
  <Router>
    <App />
  </Router>
</Provider>
Related