question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Undocumented v4 change: <Redirect> does not preserve query string

See original GitHub issue

I’m in the process of migrating from 2.x to 4.x and loving it, but I came across a change in functionality that I don’t see documented anywhere: <Redirect> no longer preserves the query string. Specifically:

// Given this:
<Redirect from='/foo' to='/bar' />

// pre-v4 behavior:
/foo?some=thing → /bar?some=thing

// v4 behavior:
/foo?some=thing → /bar

This is an issue for our codebase because we maintain a list of redirects on the client to account for legacy URL structures as our app evolves. In this case the redirects function more as 301s rather than a navigation event triggered by the user. (This list should probably be maintained on the server but let’s assume I (and probably others) don’t have that option 😅.)

I’m not advocating going back to the old logic or adding a prop to enable this behavior (though we could debate that if people wanted to I suppose), but it was a bit surprising that it isn’t mentioned anywhere in the migration docs.

Shall I open a PR to update those docs? Are there other places this should be documented?

FWIW, I plan on getting around this by rolling my own <Redirect> component, something like this:

const MyRedirect = withRouter((props) =>
  <Redirect {...props} to={props.to + props.location.search} />
)

(The above is just pseudocode to illustrate the approach, I know it’s not very robust 😉.)

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:4
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
zaknesscommented, Dec 31, 2017

I’ve had a chance to actually implement my component. Sharing it here in case it’s useful to anyone:

import _ from 'lodash'
import { Redirect as RRRedirect } from 'react-router-dom'
import { extract, stringify, parse } from 'query-string'

const mergeQueryStrings = (...args) => {
  const queryString = stringify(_.transform(args, (result, value) => {
    _.assign(result, _.isString(value) ? parse(value) : value)
  }, {}))
  return queryString ? '?' + queryString : ''
}

const Redirect = ({ preserveQueryString, ...props }) => {
  if (_.isUndefined(preserveQueryString)) {
    preserveQueryString = _.has(props, 'from')
  }
  if (!preserveQueryString || !location.search) {
    return <RRRedirect {...props} />
  }
  const { to, ...rest } = props
  const toSearch = _.isString(to) ? extract(to) : _.get(to, 'search', '')
  const search = mergeQueryStrings(location.search, toSearch)
  const nextLocation = _.isString(to)
    ? { pathname: to.split('?')[0], search }
    : { ...to, search }
  return <RRRedirect to={nextLocation} {...rest} />
}

Redirect.propTypes = {
  preserveQueryString: React.PropTypes.bool,
  // and RRRedirect propTypes, of course :)
}

export default Redirect

Example Usage:

Old Location Redirect New Location
/foo?a=b <Redirect to='/bar'> /bar
/foo?a=b <Redirect to='/bar' preserveQueryString> /bar?a=b
/foo?a=b <Redirect to='/bar?c=d'> /bar?c=d
/foo?a=b <Redirect to='/bar?c=d' preserveQueryString> /bar?a=b&c=d
/foo?a=b <Redirect from='/foo' to='/bar'> /bar?a=b
/foo?a=b <Redirect from='/foo' to='/bar' preserveQueryString={false}> /bar
/foo?a=b <Redirect from='/foo' to='/bar?c=d'> /bar?a=b&c=d
/foo?a=b <Redirect from='/foo' to='/bar?c=d' preserveQueryString={false}> /bar?c=d
0reactions
yantakuscommented, Apr 27, 2018

@AuthorProxy it will be implemented in 4.3.0. See release notes here: https://github.com/ReactTraining/react-router/releases/tag/v4.3.0-rc.1

Read more comments on GitHub >

github_iconTop Results From Across the Web

<Redirect> does not preserve query string · Issue #5818 ...
I'm in the process of migrating from 2.x to 4.x and loving it, ... Undocumented v4 change: <Redirect> does not preserve query string...
Read more >
Angular2 router keep query string - Stack Overflow
In the mean time: I believe you will need to create a component, on the path: '', with the sole purpose of then...
Read more >
RedirectMatch: how do I avoid preserving querystring
I've found a partial solution which is to append a literal "?" at the end of the url to which to redirect, so...
Read more >
#50976 (WordPress stripping out "page" query parameter with ...
This is a follow-up to #45337. I run a site and we use "page" query parameter to switch between views on that specific...
Read more >
Bash Reference Manual - GNU.org
This chapter briefly summarizes the shell's 'building blocks': commands, control structures, shell functions, shell parameters, shell expansions ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found