Fix react-router-dom for server-side rendering

This commit is contained in:
Jerko Steiner 2019-03-16 12:31:14 +05:00
parent 10b034e7f0
commit 7b682c745c
3 changed files with 20 additions and 5 deletions

View File

@ -5,6 +5,8 @@ import {IClientConfig} from './IClientConfig'
import {IRenderer} from './IRenderer'
import {IStoreFactory} from './IStoreFactory'
import {Provider} from 'react-redux'
import {Router} from 'react-router-dom'
import {createBrowserHistory} from 'history'
export interface IClientRendererParams<State, A extends Action> {
readonly createStore: IStoreFactory<State, A | any>,
@ -16,6 +18,7 @@ export class ClientRenderer<State, A extends Action> implements IRenderer {
constructor(readonly params: IClientRendererParams<State, A>) {}
render(
url: string,
config = (window as any).__APP_CONFIG__ as IClientConfig,
state = (window as any).__PRELOADED_STATE__,
) {
@ -25,11 +28,17 @@ export class ClientRenderer<State, A extends Action> implements IRenderer {
target = document.getElementById('container'),
} = this.params
const history = createBrowserHistory({
basename: config.baseUrl,
})
if (state) {
const store = createStore(state)
ReactDOM.hydrate(
<Provider store={store}>
<RootComponent config={config} />
<Router history={history}>
<RootComponent config={config} />
</Router>
</Provider>,
target,
)
@ -37,7 +46,9 @@ export class ClientRenderer<State, A extends Action> implements IRenderer {
const store = createStore()
ReactDOM.render(
<Provider store={store}>
<RootComponent config={config} />
<Router history={history}>
<RootComponent config={config} />
</Router>
</Provider>,
target,
)

View File

@ -1,5 +1,5 @@
import {IClientConfig} from './IClientConfig'
export interface IRenderer {
render(config: IClientConfig, state?: any): any
render(url: string, config: IClientConfig, state?: any): any
}

View File

@ -4,6 +4,7 @@ import {IClientConfig} from './IClientConfig'
import {IRenderer} from './IRenderer'
import {IStoreFactory} from './IStoreFactory'
import {Provider} from 'react-redux'
import {StaticRouter} from 'react-router-dom'
import {renderToNodeStream} from 'react-dom/server'
export class ServerRenderer<State, A extends Action> implements IRenderer {
@ -11,13 +12,16 @@ export class ServerRenderer<State, A extends Action> implements IRenderer {
readonly createStore: IStoreFactory<State, A | any>,
readonly RootComponent: React.ComponentType<{config: IClientConfig}>,
) {}
render(config: IClientConfig, state?: any) {
render(url: string, config: IClientConfig, state?: any) {
const {RootComponent} = this
const store = this.createStore(state)
const context = {}
const stream = renderToNodeStream(
<Provider store={store}>
<RootComponent config={config} />
<StaticRouter location={url} context={context} >
<RootComponent config={config} />
</StaticRouter>
</Provider>,
)
return stream