Setting up a React Router - javascript

All my questions become too convoluted, so i figured i'd ask like this:
https://imgur.com/a/rbeHya8
^ can this be done, and how do i do it?
I want to establish a react router, so it will update and remember url based on which page i'm on. I can't get it to work and it's driving me nuts :)
(only managed to do it directly from Paging.js, by wrapping buttons with < Link > tag and setting them directly to={/page/{api.id}} but that didn't work when i uploaded the app to github, because the browser didn't recognize the suffix as legit, so if i reloaded on /page/x it crashed and gave me 404. basically the link wasnt connected to anything, just gave a pseudo url)

You need to use a react router dom hook called useParams()
import { useParams } from 'react-router-dom'
const Page = () => {
const { id } = useParams()
return (
<div>
<h1>Page id: {id}</h1>
</div>
)
}
export default Page

Related

Impossible to get part of URL with react router?

How can I always get the same part of the URL in react?
example:
http://localhost:3000/supplier/924511e8-9056-4c1e-9976-625bf042924e
I only want "supplier", but this can be anything else. So it's possible for it to be:
http://localhost:3000/product/924511e8-9056-4c1e-9976-625bf042924e
Then I want "product"
But it can also be just http://localhost:3000/supplier/ also in this case I only want the supplier. And this can be anything.
How do I do this? If I've already tried it with pathname.slice(0, pathname.indexOf("/") but this doesn't seem to work.
So I only want the string after the http://localhost:3000/want this/ no matter if there is anything after it or not.
You can use the split method as below:
const url = 'http://localhost:3000/supplier/'
const want_this = url.split('/')[3]
Just use useParams from react router dom
import {useParams} from "react-router-dom";
function Child() {
// We can use the `useParams` hook here to access
// the dynamic pieces of the URL.
let { id } = useParams();
return (
<div>
<h3>ID: {id}</h3>
</div>
);
}

React: change url without rerender; using window.history?

I have a "settings" page in my react app. The page has several tabs rendering different parts of settings.
It would be better UX if a user can share urls with other users.
What I want is (inside "settings" page):
user A clicks a tab
url changes with a #tabname appended
user A send that url to user B, and user B open that url
user B sees the same tab as user A
But with react router, the whole page re-renders if the url changed:
import { withRouter } from "react-router-dom"
const MyComp = (props) => {
...
const onTabChange = () => {
// append #tabname here
props.history.replace(...); // or `push`
...
}
...
export default withRouter(MyComp)
}
After a lot of searches, I found a solution to use window.history:
const onTabChange = () => {
window.history.pushState(null, null, "#tabname");
...
}
This does the trick, but little information and explanation, and I'd love to know the consequences of using this trick.
Is this a valid solution (for a react app)? Will this cause any problem?
(PS. I know how to parse a url)
More details:
To be more specific, there is a AuthChecker wrapper for all pages. When react router's location changes, it checks for the route's allowed auths and current user's auth.
I've tried /path/:id and everything but all change location, so auth checked and page rerendered.
And I've given up a solution in react router and just want to know: is it safe to change url with window.history in a react app using react router to manage routes?
this question is already answerd at this post.
so it says window has a property called history and there is a method on history which helps you update the history state without react-router-dom understanding it.
like this:
window.history.replaceState(null, 'New Page Title', '/new_url');

Get Target Path in Gatsby [duplicate]

This question already has answers here:
How to get previous url in react gatsby
(4 answers)
Closed 2 years ago.
Is there any way to find the path of the page that a user is on on a Gatsby site and store it in a const so that it can be checked next to the current path the user is on? In other words if they're on the /about page, and are clicking a link to navigate to the /contact page, I need to get the paths of both so that I can check them against each other. I know I can get location.pathname for the current url, but how do I find the path that they are navigating to when the click a link?
Since your code structure isn't clear. Assuming a simple anchor tag, you can do something like this:-
<a href="/new/link" onClick={getHref}>New Link</a>
And in your getHref method
function getHref(event){
console.log(event.target.href); // should log '/new/link'
}
Check if this works in your case.
Please forgive for any typo, I havent validated it.
Gatsby exposes props (because it extends from #reach/router from React) by default on the top-level components (this means pages). You can pass it to the child components as you wish or store it in a const or in a React's state.
Without knowing any page structure, I'll provide something dummy as an example:
import React from "react"
import { graphql } from "gatsby"
const YourPage = ({ location, data }) => {
console.log('your page is ', location.pathname)
return <div>Dummy content</div>
}
export default Page
export const query = graphql`
query PageQuery {
site {
siteMetadata {
siteURL
}
}
}
`
Your information is stored under props.location, that's why you can destructure it in the component's declaration.
In the case above, I've used pathname property but you have a bunch exposed. Check it out to find out which one fits your requirements.

Printing the current URL in React/JS

I would like to print the URL in screen (yes it's written in the URL bar, but I would like to do it anyway)
What can I use ?
In the following example, what can I write instead of {iDontKnowWhatToWriteHere} to give the curent URL ?
import React from 'react';
class Connexion extends React.Component {
render() {
return (
<h1> the URL is {iDontKnowWhatToWriteHere} </h1>
)
}
}
Thank you
React is a normal javascript library that takes care just of the view of your application, so It allows you to access all the normal browser APIs and properties availables and one of them is location.
So if you want to access the actual url in React you should do it in the way that you would do it without React (Except when you're using some especific library for that problem like react-router), just:
If you want to get all the url (Including the domain, protocol, port)
window.location.href
Or if you just want the path after de domain
window.location.pathname
In your code
import React from 'react';
class Connexion extends React.Component {
render() {
return (
<h1> the URL is {window.location.pathname} </h1>
)
}
}
Assuming that you use React Router you can use
return (
<h1> the URL is {this.context.location.pathname} </h1>
)
You can get information about your url using the window.location object that is provided by vanilla JavaScript.
For reference, see https://www.w3schools.com/jsref/obj_location.asp
You could use window.location.href to get the full url. Attached is a screenshot of the location object (I got it from Chrome web console)
If you are using react-router. Try:
this.props.location.pathname
Regards

Prevent react-router history.push from reloading current route

I'm taking my first steps with react-router.
I'm currently using the hashHistory for development purposes and I'm performing 'manual' navigation. That is to say, I'm not using Link and I'm invoking history.push('/some/route'); in order to navigate (in response to plain old clicks on anchor tags).
What I'm noticing is that, even when I'm already on the target route, react-router will re-render the relevant target component every time history.push('/target/route'); is invoked: On every push('/target/route'):
the fragment part of the URL remains #/target/route
the query string part of the URL changes to ?_k=somethingRandom
the target component re-renders
I would like for that re-rendering to not happen - I actually expected history.push to be a no-op when I'm already at the route that I'm attempting to push.
I'm apparently missing something, as this is not what's happening. Funnily enough I'm seeing posts from people who are trying to achieve the behaviour that I'd like to get rid of - they'd like to 'refresh' a route without leaving it, so to speak. Which looks pretty much like the opposite problem :).
Could you enlighten me as to what it is I'm misunderstanding and how I would achieve the desired behaviour? Is this perhaps something that would go away if (when) I switch to browserHistory?
My guess is that your component re-renders because something in your prop changes when you make a router push. I suspect it might be the action or key properties of prop.location. You could always check all the values of prop during each render to see what changes.
You can solve this issue by comparing your old route path with the new one in the shouldComponentUpdate life-cycle method. If it hasn't changed you are on the same route, and you can prevent the re-rendering by returning false. In all other cases, return true. By default this always returns true.
shouldComponentUpdate: function(nextProps, nextState) {
if(this.props.route.path == nextProps.route.path) return false;
return true;
}
You'll have to make further checks as well as this will prevent your component from updating on state updates within the component as well, but I guess this would be your starting point.
Read more about shouldComponentUpdate on the official react docs page.
Use this as an opportunity to return false when you're certain that the transition to the new props and state will not require a component update.
I have the same issue and i find the (dumb) solution.
You just have a <button> (button by default is type=submit) or something similar (form, submit.... etc) thats is reloading the page like a html <form method=GET ...>.
Check it in your code, and remove it.
PD:
_k=somethingRandom > this is just the value inputs (or the button) that you are sending in the form.
I will give this a shot...
If you land here and looking to change your URL (for sharing purposes for example) then RR docs already has the solution described. Just make sure you do not use the history within the component (i.e. this.props.history.push())as you will be (as expected) routed to the target. You are however allowed to access your browser history without any interference with the component's history.
Following tested only on Chrome
// history.js
import { createBrowserHistory } from 'history'
export default createBrowserHistory()
and then from your XYZ component
// XYZ.js
import React from 'react';
import history from './history'
class XYZ extends React.Component {
_handleClick() {
// this should not cause rerender and still have URL change
history.push("/someloc");
}
render() {
return(
<button onClick={this._handleClick.bind(this)}>test </button>
)
}
}
Hope it helps someone else.
In App.js:
shouldComponentUpdate(nextProps, nextState) {
return nextProps.location.search === this.props.location.search
}
I think the easier workaround maybe replacing the Route with our own route
import { Route, withRouter } from "react-router-dom";
function MyRoute({ key, path, exact, component: Component, history }) {
let lastLocation = null;
return (
<Route
key={key}
path={path}
exact={exact}
render={(props) => {
history.listen((location) => {
lastLocation = location;
});
// monkey patching to prevent pushing same url into history stack
const prevHistoryPush = history.push;
history.push = (pathname, state = {}) => {
if (
lastLocation === null ||
pathname !==
lastLocation.pathname + lastLocation.search + lastLocation.hash ||
JSON.stringify(state) !== JSON.stringify(lastLocation.state)
) {
prevHistoryPush(pathname, state);
}
};
return <Component {...props} />;
}}
/>
);
}
export default withRouter(MyRoute);
We use this as a wrapper for actual Route of react-router-dom and it works perfectly for me.
for more please refer here
tsx sample
import {createBrowserHistory} from 'history';
export const history = createBrowserHistory();
ReactDOM.render(
<Router history={history}>
<App/>
</Router>,
document.getElementById("root")
);

Categories