Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow URLs to be skipped from react-router and passed to server #3109

Closed
rskumar opened this issue Feb 22, 2016 · 12 comments
Closed

Allow URLs to be skipped from react-router and passed to server #3109

rskumar opened this issue Feb 22, 2016 · 12 comments

Comments

@rskumar
Copy link

rskumar commented Feb 22, 2016

For few scenarios, developer may want to skip react-router from handling some urls and rather refresh from server. Example url - '/help' may be different section than Single page app using React+router.
Clicking '/help' should then skip react-router from matching and transitioning to NotFound, rather should be rendered from server-side.

@taion
Copy link
Contributor

taion commented Feb 22, 2016

Out of scope.

@taion taion closed this as completed Feb 22, 2016
@timdorr
Copy link
Member

timdorr commented Feb 22, 2016

You can do this by just putting that route handler ahead of whatever middleware function handles your router URLs. It'll short circuit and you can avoid the router entirely.

@rskumar
Copy link
Author

rskumar commented Feb 22, 2016

Is short-circuiting possible in client side route declarations?

@rskumar
Copy link
Author

rskumar commented Feb 22, 2016

For workaround, one of my friend wrote ServerLink component (shamelessly copied Link code from react-router), and changed onClick code with
window.location.href = this.props.to;
This works.

@rskumar
Copy link
Author

rskumar commented Feb 28, 2016

Looking into Link code, found it skips transitioning to next state if target prop is available, and let browser handle it. So,
<Link to="/someurl" target="_self">...</Link>
can be used to send request to server. It works.

@mateodelnorte
Copy link

Hi all,

I'm trying to sort out an issue that's not obvious. I have a number of routes set up like the following:

  <Switch>
    <Route exact path="/" component={Home}/>
    <Route exact path="/home-chinese" component={HomeChinese}/>
    <Route path="*" component={NotFound}/>
  </Switch>

I also have a few links scattered around my app that look like the following:

<a href="/some-server-route" target="_blank" rel="noopener noreferrer">
  <p className="btn-text-1">go to my server route, not a react route</p>
</a>

my app.js contains:

app.use(helmet());

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(express.static(path.join(__dirname, 'public')));

if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, 'build')));
} else {
  app.use(express.static(path.join(__dirname, 'build', 'static')));
}

app.use((req, res, next) => {
	if (config.NODE_ENV === 'development') return (logger('tiny')(req, res, next));
	if (req.path === '/') return next();
	return logger(function (tokens, req, res) {
		return [
			tokens.method(req, res),
			tokens.url(req, res),
			tokens.status(req, res),
			tokens.res(req, res, 'content-length'), '-',
			tokens['response-time'](req, res), 'ms'
		].join(' ')
	})(req, res, next);
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());

app.use('/', index);

// Always return the main index.html, so react-router render the route in the client
app.get(/.*/, (req, res) => {
  return res.sendFile(path.resolve(__dirname, 'build', 'index.html'));
});

and index.js contains:

router.get('/some-server-route', (req, res) => {
  res.redirect('/assets/some-local-file');
});

For some reason, people on different machines seem to be getting different behavior. Some people are correctly served some-local-file and others are getting a 404 from the client side routes.

Any idea why this would be happening?

@OleksandrSachuk
Copy link

@mateodelnorte Thanks a lot. You decision works for me:
router.get('/some-server-route', (req, res) => {
res.redirect('/assets/some-local-file');
});

@damiangreen
Copy link

My wrapper component using @rskumar's answer above, in case it helps anyone.

import React from 'react'
import PropTypes from 'prop-types'
import { Link as ReactRouterLink } from 'react-router'
import { urlInsinglePageApplicationUrlWhiteList } from 'services/urlService'

// This component renders a react router link if it's part of
// the Single Page Application, otherwise renders a normal link
export default class Link extends React.Component {
  static propTypes = {
    url: PropTypes.string.isRequired,
    children: PropTypes.node
  }

  render () {
    const { url, children, ...rest } = this.props

    return urlInsinglePageApplicationUrlWhiteList(url)
      ? <ReactRouterLink to={url} {...rest}>
        {children}
      </ReactRouterLink>
      : <ReactRouterLink to={url} {...rest} target='_self'>
        {children}
      </ReactRouterLink>
  }
}

@markptrueman
Copy link

@mateodelnorte Did you ever get to the bottom of your issue above? I have the same thing with one of my endpoints which goes to 404 for some clients. I think it's something to do with service-worker, but im struggling to work it out

@xtools-at
Copy link

xtools-at commented Jul 14, 2018

@markptrueman same here :(
EDIT: I think I've solved it for my case by adding the static html files I wanted to load to the service workers staticFileGlobs

@franciscop-invast
Copy link

Yup, the obvious one is... using a traditional anchor tag:

<a href="/help">Help me!</a>;

That will just get you there without any routing magic.

@xtools-at
Copy link

Well, not if you use a service worker, which serves the index.html for routes it doesn't know. /help/index.html works, but /help is still resolved within the react app :(

@lock lock bot locked as resolved and limited conversation to collaborators Sep 24, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants