I am using react-router-dom hook useLocation() in third party component.
This component behavior depends on the current route by default but can be used also in app without react-router (user of the component shouldn't care about it)
The problem is that when the component is used outside of react-router scope it throws an error:
Cannot read property 'location' of undefined
My question is how to know if I can use useLocation() hook (how to know if a component is in react-router context)?
The simplest solution from a similar question suggested by #Krzysztof Cieslinski is wrapping useLocation() hook in try/catch block:
let path = ''
try {
path = useLocation().pathname
} catch (e) {}
Related
There is BasicLayout.jsx in my application which pass down the props for main components and render the child components inside the layout. I want to perform some logic depends on URL changes inside the useEffect() of BasicLayout.jsx. Is there any efficient way to detect any URL changes with useLocation hook?
In this case that I want to re-render the BasicLayout.tsx, I used useHistoy() hook instead of useLocation() and passed the current URL pathname as dependency to the useEffect().
Here is the code snippet:
import { useHistory } from 'react-router-dom';
let url = useHistory();
useEffect(() => {
...
// perform some logic
...
}, [currentUser, declaration, url.location.pathname]);
so i was using redirect in react-router-dom, i have 2 pages, home and create when the form in create is done and has been submitted, it will execute the <Redirect> function, and it works, but the ComponentDidMount was not being fired again, i need to reload the page to make the ComponentDidMount to make it start again, here is my code
this is how i redirect in the Create file :
if(this.state.createNew){
return <Redirect to='/home'/>
}
and this is my ComponentDidMount in my Home file :
componentDidMount() {
console.log("hi")
}
the console print hi only on the initial render, when i redirect back to the page it does not fire again, i tried use setState inside the ComponentDidMount but it still not being re rendered.
when i tried using Link to method, it works, the ComponentDidMount is being fired again, but Link to is not what i want, because it does not automatically redirect like the <Redirect> do
i got an error when i try to use the useHistory function :
React Hook "useHistory" is called in function "simpan" which is neither a React function component or a custom React Hook function react-hooks/rules-of-hooks
here is how i use my useHistory :
function simpan(event){
event.preventDefault()
const email = event.target.elements.email.value
const name = event.target.elements.name.value
const admin = event.target.elements.admin.value
const active = event.target.elements.active.value
const history = useHistory()
console.log(email)
history.push('/home')
}
thanks before, anyhelp will be appriciated
instead of <Redirect /> why don't you use history.push('/home'). this will take you to the new route once state is true and call componentDidMount
how to use history:
import { useHistory } from 'react-router-dom'
then inside your component: const history = useHistory()
then whether you need to change the route:
history.push('/home')
If your create is class component just use this.props.history.push("/home") instead of <Redirect> tag.
As create component is your route it will automatically get history object in props.
why to use history instead of redirect tag in your case
Simple example of programatic navigation with react routing Please check console of browser while checking this example
I'm writing a react app which uses react-router-dom for routing. For one of the routes I have to perform an action when the user leaves (perform api request & stop the timer).
I can do this either
In the cleanup function returned by useEffect hook inside the component rendered for that route
or
Attach to the router and detect the route changes.
Which way is better? Or perhaps there's some other way?
You can use componentWillUnmount. However, useEffect works just as well!
That is likely the better way to handle this event.
I will try to use react router tools to make effects when your are navigating.
Unmount is kind of side effect of navigation, but maybe could not unmount, or you can unmount that component for other reasons.
if you are using hooks maybe you can use useLocation and store what is the current page and do something like this:
function usePageViewTracker() {
const location = useLocation()
[lastLocation, setLastLocation] = useState('')
useEffect(() => {
if (lastLocation === 'specialLocation') {
// call your API
}
setLastLocation(location)
}, [location])
}
How do I get the full URL from within a ReactJS component?
I'm thinking it should be something like this.props.location but it is undefined
window.location.href is what you're looking for.
If you need the full path of your URL, you can use vanilla Javascript:
window.location.href
To get just the path (minus domain name), you can use:
window.location.pathname
console.log(window.location.pathname); //yields: "/js" (where snippets run)
console.log(window.location.href); //yields: "https://stacksnippets.net/js"
Source: Location pathname Property - W3Schools
If you are not already using "react-router" you can install it using:
yarn add react-router
then in a React.Component within a "Route", you can call:
this.props.location.pathname
This returns the path, not including the domain name.
Thanks #abdulla-zulqarnain!
window.location.href is what you need. But also if you are using react router you might find useful checking out useLocation and useHistory hooks.
Both create an object with a pathname attribute you can read and are useful for a bunch of other stuff. Here's a youtube video explaining react router hooks
Both will give you what you need (without the domain name):
import { useHistory ,useLocation } from 'react-router-dom';
const location = useLocation()
location.pathname
const history = useHistory()
history.location.pathname
this.props.location is a react-router feature, you'll have to install if you want to use it.
Note: doesn't return the full url.
Plain JS :
window.location.href // Returns full path, with domain name
window.location.origin // returns window domain url Ex : "https://stackoverflow.com"
window.location.pathname // returns relative path, without domain name
Using react-router
this.props.location.pathname // returns relative path, without domain name
Using react Hook
const location = useLocation(); // React Hook
console.log(location.pathname); // returns relative path, without domain name
You are getting undefined because you probably have the components outside React Router.
Remember that you need to make sure that the component from which you are calling this.props.location is inside a <Route /> component such as this:
<Route path="/dashboard" component={Dashboard} />
Then inside the Dashboard component, you have access to this.props.location...
Just to add a little further documentation to this page - I have been struggling with this problem for a while.
As said above, the easiest way to get the URL is via window.location.href.
we can then extract parts of the URL through vanilla Javascript by using let urlElements = window.location.href.split('/')
We would then console.log(urlElements) to see the Array of elements produced by calling .split() on the URL.
Once you have found which index in the array you want to access, you can then assigned this to a variable
let urlElelement = (urlElements[0])
And now you can use the value of urlElement, which will be the specific part of your URL, wherever you want.
To get the current router instance or current location you have to create a Higher order component with withRouter from react-router-dom. otherwise, when you are trying to access this.props.location it will return undefined
Example
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class className extends Component {
render(){
return(
....
)
}
}
export default withRouter(className)
Read this I found the solution of React / NextJs. Because if we use directly used the window.location.href in react or nextjs it throw error like
Server Error
ReferenceError: window is not defined
import React, { useState, useEffect } from "react";
const Product = ({ product }) => {
const [pageURL, setPageURL] = useState(0);
useEffect(() => {
setPageURL(window.location.href);
})
return (
<div>
<h3>{pageURL}</h3>
</div>
);
};
Note:
https://medium.com/frontend-digest/why-is-window-not-defined-in-nextjs-44daf7b4604e#:~:text=NextJS%20is%20a%20framework%20that,is%20not%20run%20in%20NodeJS.
As somebody else mentioned, first you need react-router package. But location object that it provides you with contains parsed url.
But if you want full url badly without accessing global variables, I believe the fastest way to do that would be
...
const getA = memoize(() => document.createElement('a'));
const getCleanA = () => Object.assign(getA(), { href: '' });
const MyComponent = ({ location }) => {
const { href } = Object.assign(getCleanA(), location);
...
href is the one containing a full url.
For memoize I usually use lodash, it's implemented that way mostly to avoid creating new element without necessity.
P.S.: Of course is you're not restricted by ancient browsers you might want to try new URL() thing, but basically entire situation is more or less pointless, because you access global variable in one or another way. So why not to use window.location.href instead?
Is there an easy way to return the current router address.
IE, if I'm on page, and I just want to see what page I'm on according to the react router.
So, localhost/admin/users would return admin/users
Obviously, I can get the same results by parsing the location, but I was wondering if react router provides a simple mechanism to do this, the same way it provides the params props?
If you're using 1.0 or newer, you have the location as a prop in your React components that are matched against a route. So you just type
this.props.location.pathname
to get what you wanted.
this.props.location.pathname gives only the routing path.
window.location.href gives you the full URL, as suggested here https://stackoverflow.com/a/39823749/7560899
For React Functional Component
import { useLocation } from 'react-router-dom';
const MyComponent = () => {
let location = useLocation();
...useState
useEffect(() => {
console.log(location.pathname);
}, []);
return ();
};
export default MyComponent;
There are many other options:
https://dev.to/finallynero/hooks-introduced-in-react-router-v5-1-7g8
You can also try
location.pathname
It may work while other methods don't as it did to me
For a non-react, pure javascript based solution using the browser window object.
Let's say the current page URL is something like this https://hostname:port/path?query.
window.location.href // returns the full URL 'https://hostname:port/path?query'
window.location.pathname // returns just the 'path' part of the full URL.
window.location.search // returns just the '?query' part of the full URL.
window.location.port // returns the 'port'.
window.location.hostname // returns just the 'hostname' part of the URL.
window.location.host // returns the hostname and port (hostname:port) part of the URL.
window.location.protocol // returns the protocol (https)
window.location.origin // returns the base URL (https://hostname:port)
See https://developer.mozilla.org/en-US/docs/Web/API/Location for more details.
for react-router-dom v6
const { pathname } = useLocation();
import if somebody need it
import { useLocation } from "react-router-dom";
window.location will give the full path.
this.props.location.pathname - it may not give the full path. use this, if you want just the URL path without the domain prefix. (also, I may suggest using context API to get this in any child components instead of passing this as props)
one more example, to implement the new component with social share feature, you may need to use the window.location and not the location.pathname.