13

I'm trying to use a percent sign in a react-router id. As using % in URI is forbidden, I have to encode my URI manually to be able to use this percent sign. Using a Link, I therefore use the encodeURI function to encode the URI:

<Link to={`/r/${encodeURI(my_str_with_unencoded_percent_sign)}`} >

In the source code of my page, I can see that the link uses %25 and not %.

Still, when clicking on the link, I get the error "URIError: malformed URI sequence" (in another part of my code, I have a <Match pattern="/r/:id" …).

What did I do wrong? It seems the url is decoded before being passed to the parseParams function of react-router, which tries to decode it a second time, which leads to this error.

I found issues such as https://github.com/ReactTraining/history/issues/461 or https://github.com/ReactTraining/history/issues/461, but I didn't find any solution to this problem: how can I use a percent sign in a react-router :id ?

1 Answers1

-1

Here is a working modified version of the URL Parameters example provided by Recat-Training.

Copy paste the below into your index.js and test it to see it works. I was going to provide a codesandbox of this for you, but their internal routing has issues that cause the screen to go black even with uri encoded % signs... I did test this locally and works like a charm.

import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

const ParamsExample = () => (
  <Router>
    <div>
      <h2>Accounts</h2>
      <ul>
        <li><Link to={`/${encodeURI("%netflix")}`}>Netflix</Link></li>
        <li><Link to="/zillow-group">Zillow Group</Link></li>
        <li><Link to="/yahoo">Yahoo</Link></li>
        <li><Link to="/modus-create">Modus Create</Link></li>
      </ul>

      <Route path="/:id" component={Child} />
    </div>
  </Router>
)

const Child = ({ match }) => (
  <div>
    <h3>ID: {match.params.id}</h3>
  </div>
)

render(<ParamsExample />, document.getElementById("react"));
Kyle Richardson
  • 5,567
  • 3
  • 17
  • 40
  • 1
    Hi. Thank you for your answer. Indeed, your solution works when I click the links displayed on the page, but it does not work when refreshing the page: if I click on the « Netflix » link, it correctly shows me the ID, as expected, and it changes the URL in my web navigator to "http://domain.tld/%netflix". When refreshing using F5, or ctrl+R, I still get the same error. Is that expected? Test code is here (only here for easy zip download, as you said, codesandbox is broken and shows a web page): https://codesandbox.io/s/zj7ok3l5x –  Dec 24 '17 at 14:53
  • You're getting a `malformed url` error from trying to navigate directly to a url that contains a `%` or a url that contains an encoded `%`? – Kyle Richardson Dec 24 '17 at 17:10
  • Well, the url contains a % (non encoded, in the url bar), while it should contain an encoded % as I use the encodeURI function. Still, react-router understand the encoding, as clicking on the links redirects to the correct Route. –  Dec 24 '17 at 20:31
  • But the link directs you to the encoded version. `to={`/${encodeURI("%netflix")}`}`. If you want people to be able to direct link with a `%` in the url, I would look at the `window.location.pathname` prior to any routing in my app. If any characters that need to be encoded are present, redirect to an encoded version of the url. – Kyle Richardson Dec 24 '17 at 21:47
  • The link should directs me to the encoded version, but it is not: if I look in the url shown in my navigator, the url is not encoded (with the codesandbox.io above). I made a video to show you the issue: https://ptpb.pw/UBJc.mkv –  Dec 24 '17 at 22:13
  • This is a bug in the [react router history library](https://github.com/ReactTraining/history/issues/505). [This PR](https://github.com/ReactTraining/history/pull/751) will need to get merged, and react router will need to bump its version. – James Conkling Nov 07 '19 at 23:36