Reputation: 15698
I'm trying to create a feature where when a user clicks on a <Link>
, they navigate to another component (Post) and scroll directly to a Comment. The path satisfies the requirements for the <Route>
definition, but when I use a "#" as part of the URL, the redirect does not take affect:
Route: <Route path="/post/:id/:hash" component={Post} />
URL: https://b881s.codesandbox.io/post/4/#ve33e
However, what's interesting is that the feature works as expected when I use a "@" instead of "#".
URL: https://b881s.codesandbox.io/post/4/@ve33e
I've tried to find any mentions of "#" being some sort of special character to react-router-dom
, but have not found anything. Maybe there's something I'm fundamentally missing here?
Here's the sandbox with working code: https://codesandbox.io/s/scrollintoview-with-refs-and-redux-b881s
App.js
import React from "react";
import ReactDOM from "react-dom";
import Home from "./Home";
import Posts from "./Posts";
import Post from "./Post";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import store from "./store";
import { Provider } from "react-redux";
import "./styles.css";
const App = () => {
return (
<Provider store={store}>
<BrowserRouter>
<div>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/posts" component={Posts} />
<Route path="/post/:id/:hash" component={Post} />
<Route path="/post/:id/" component={Post} />
</Switch>
</div>
</BrowserRouter>
</Provider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
class Posts extends React.Component {
createPostList = () => {
const { posts } = this.props;
if (posts.posts) {
return posts.posts.map(post => {
return (
<div key={post.id} className="post">
<Link to={`/post/${post.id}`}>{post.title}</Link>
<p>{post.text}</p>
<div>
{post.comments.map(comment => {
return (
<div>
<Link to={`/post/${post.id}/@${[comment.id]}`}>
{comment.id}
</Link>
</div>
);
})}
</div>
</div>
);
});
} else {
return <h4>Loading...</h4>;
}
};
render() {
return <div>{this.createPostList()}</div>;
}
}
const mapStateToProps = state => {
return {
posts: state.posts
};
};
export default connect(mapStateToProps)(Posts);
Upvotes: 1
Views: 1403
Reputation: 490
Use %23 as a hash sign, should definitely solve it.
More information about it: https://en.wikipedia.org/wiki/Percent-encoding
Here is a forked from you, that I use %23 to represent #
https://codesandbox.io/s/scrollintoview-with-refs-and-redux-z8pz8
Upvotes: 0
Reputation: 29285
Anything after #
in a URL string is called hash. You can access the hash for a given location
using location.hash
. So in your routes you won't need to mention :hash
. You should instead read the hash through the location
object injected to the component by the Route component.
Your Route:
<Route path="/post/:id" component={Post} />
To read hash in Post
component:
class Post extends React.Component {
render() {
const {location} = this.props;
console.log(location.hash);
...
}
}
Upvotes: 1