markdalgleish/redial

React Router v4 support?

idangozlan opened this issue · 8 comments

Hi,

Can you supply React Router v4 installation guide? since they removed match function the current installation instructions are not valid anymore.

Thanks!

@idangozlan These'a an example from (server-rendering document](https://reacttraining.com/react-router/web/guides/server-rendering) for RR4:

import { matchPath } from 'react-router-dom'

// inside a request
const promises = []

routes.some(route => {
  const match = matchPath(req.url, route)
  if (match)
    promises.push(route.loadData(match))
  return match
})

Promise.all(promises).then(data => {
  // do something w/ the data so the client
  // can access it then render the app
})

Maybe it will helps you

Thank you @ufocoder, but unfortunately that doesn't really related to my question, a solution is needed asap. @markdalgleish, is that project still under maintenance? any plans to create an example for React Router 4?

@idangozlan Not sure you saw this, but it looks like React Training is actively developing another package to address the support issues with data loading. https://github.com/reacttraining/react-router/tree/master/packages/react-router-config . The problem is that React Router 4 is designed to be dynamic, which means it cannot be statically evaluated without rendering the entire page. This new React Router Config allows for static declaration of routes that are compatible with React Router 4.

Personally I'm sticking with React Router 2 until this stuff is fully resolved.

@markdalgleish What router can be used with redial?
What about universal-router?

Simplest example - you can use matchRoutes from react-router-config

SSR React-Router v4 & express.js

import { matchRoutes } from 'react-router-config'

...

app.get('*', async (req, res, next) => {
  const store = createStore(reducer, applyMiddleware(thunk));
  const branch = matchRoutes(routes, req.path)

  // Just get components
  const components = branch.map(b => b.route.component)

  const locals = {
    dispatch: store.dispatch
  }

  try {
    await trigger('fetch', components, locals)

    const preloadedState = store.getState()
    // Render your app with preloaded state
  } catch (err) {
    // error handling 
  }
})

And on Client there are no longer { browserHistory }
But you can do:

...

const store = createStore(reducers, preloadedState) 

const Listener = (props, context) => {
  context.router.history.listen(props.onListen)
  return props.children
}

Listener.contextTypes = {
  router: PropTypes.object.isRequired
}

const listenHistory = (location, action) => {
  const branch = matchRoutes(routes, location.pathname)
  const components = branch.map(b => b.route.component) // You can use .pop() to fetch only from deepest component
  trigger('fetch', components, { dispatch: store.dispatch })
}

hydrate(
  <Provider store={store}>
    <BrowserRouter>
      <Listener onListen={listenHistory}>
        {renderRoutes(routes)}
      </Listener>
    </BrowserRouter>
  </Provider>
  , document.getElementById('root')
)

I am having this same problem.

I would like to realize an isomorphic web application using react router v4, redux, redial, but it will not work quite well.

I tried @pablo-bl code, but it will be out if there is no history. How can we solve this?

2018-06-08 10 57 30

clientDesktop.tsx code here.

import * as React from "react";
import { matchRoutes, renderRoutes } from 'react-router-config'
import { hydrate } from "react-dom";
import { Provider } from "react-redux";
import { trigger } from "redial"
import { BrowserRouter } from "react-router-dom";
import configureStore from "./store";
import route, { routes } from "./router/desktop";

const supportsHistory = "pushState" in window.history;

const __STATE__ = (window as any).__STATE__;
const store = configureStore(__STATE__);

const Listener = (props, context) => {
  context.router.history.listen(props.onListen)
  return props.children
}

const listenHistory = (location, action) => {
  const branch = matchRoutes(routes, window.location.pathname)
  const components = branch.map(b => b.route.component)
  trigger("fetch", components, { dispatch: store.dispatch })
}

hydrate(
  <Provider store={store}>
    <BrowserRouter forceRefresh={!supportsHistory}>
      <Listener onListen={listenHistory}>
        {renderRoutes(routes)}
      </Listener>
    </BrowserRouter>
  </Provider>,
  document.getElementById("app")
);

I'm already suffering from this problem too much and my gray hair is getting more serious :(