Navigating From One local Host to another in react js - reactjs

How can i navigate from one localHost:3000 to localHost:3001 in react Js
currently my auth is running in localHost:3000 and i want to navigate it to localHost:3001 when login successful
my current implementation is like
{agency && <Navigate to={"http://localhost:3001/"} replace />}
but it navigate me to http://localhost:3000/Login/localhost:3001/
but i want http://localhost:3001
Anyone?

react-router-dom only handles internal navigation actions, i.e. it can only link to and route within the React application. "http://localhost:3001/" is interpreted as an internal path and is appended to the current path.
If you need to navigate to an external (to the app) URL you should use raw anchor (<a />) tags or issue an imperative redirect via the window.location object.
Create a new navigation component to handle issuing the side-effect of external redirect in an useEffect hook.
Example:
const NavigateExternal = ({ to }) => {
useEffect(() => {
window.location.href = to;
}, []);
return null;
};
...
{agency && <NavigateExternal to="http://localhost:3001/" />}

You'd need to use
window.location.href = 'http://localhost:3001/'
Or using good practices
const redirectToExternalResource = url => window.location.href = URL
redirectToExternalResource('http://localhost:3001/')

Related

React Native Navigation, open universal link from within own app

I am using React Navigation for React Native. I have successfully configured it to handle universal link, which is something like this
// linking.ts
import { APP_ID } from '#env';
const config = {
screens: {
LoginScreen: 'authorize',
RegisterScreen: 'register',
CustomerStack: {
screens: {
OrderDetailScreen: 'customer/order/:orderId',
},
},
},
};
const linking = {
prefixes: [`${APP_ID}://app/`, 'https://example.com/app/'],
config,
};
export default linking;
// App.tsx
import linking from './linking'
const App = () => {
return (
<NavigationContainer linking={linking}> <MyApp /> </NavigationContainer>
)
}
When I press a link in the browser such as https://example.com/app/customer/order/1234, then it successfully opens my app's order page.
Problem
I want to be able to open the url such as https://example.com/app/customer/order/1234 indside my app and have it open the order page. I have tried
<Button onPress={() => Linking.openURL('https://example.com/app/customer/order/1234')} />
but (testing on IOS) it switch to the web browser first to open the link, and then open my app.
Is it possible to open the order page directly inside my app without switching to the browser first.
Note: I am trying to implement an in-app notification history page, each notification item has the link saved in the database, and when the user clicks on the item I want to navigate the user to the page as configured in linking.ts. I know it is possible to parse the link and use navigation.navigate() instead, but that means I will have 2 places for the linking configuration. I think it would be great if I can reuse the existing logic provided by React Navigation.
In React Navigation, you can use the useLinkTo hook. This hook allows you to navigate inside the application using a path.
This will allow you to use the following option:
const linkTo = useLinkTo();
return (
<Button onPress={() => linkTo('/customer/order/1234')} />
);
If using a URL is mandatory, then you can use extractPathFromURL, an internal React Navigation function, to remove the prefix.
import extractPathFromURL from '#react-navigation/native/src/extractPathFromURL';
import linking from './linking'
// ...
const linkTo = useLinkTo();
return (
<Button onPress={() => {
const path = extractPathFromURL(linking.prefixes, 'https://example.com/app/customer/order/1234');
const pathWithSlash = path.startsWith('/') ? path : '/' + path;
linkTo(pathWithSlash);
} />
);
extractPathFromURL is not part of the official API and may be removed in future versions. For reliability, you can create a duplicate of this function in the project.

How to fetch data before route change?

I'm trying to have the following user flow when a user click on a link:
The user clicks on a link
A progress bar appears at the top of the page
The JS launches a network request to fetch some data from the server
When done, the progress bar finishes, and the page is switch
Note that I don't want to have any spinner or skeleton page. When the user clicks on the link, the page should not change at all (apart from the progress bar appearing) until the data has been fetched from the server, similar to how GitHub works.
I've searched a lot about this on the last few days, and it seems that it's not possible to do this:
Apparently, there used to be a onEnter hook that made it possible to achieve my described flow, but it was removed because, according to the devs, React lifecycle hooks were enough to achieve this.
React lifecycle hooks are not enough because if I use them to trigger the network request, the page will be blank between the click on the link and the response of the network request.
I could make a wrapper on top of the Link component so that when the user clicks on it, the network request is triggered and only after it's finished, router.navigate would be called. It seems nice at first, but it doesn't solve the issue of the initial visit to a page, where a Link button has not been called at all.
Any ideas on how to achieve this?
Thanks in advance!
I created a workaround for such behaviour: react-router-loading. It allows you to fetch data before switching the page.
You only need to replace Switch / Routes and Route with ones from the package, mark some (or all) routes with the loading prop and tell the router when to switch pages using the context in components:
import { Routes, Route } from "react-router-loading";
<Routes> // or <Switch> for React Router 5
<Route path="/page1" element={<MyPage1 />} loading />
<Route path="/page2" element={<MyPage2 />} loading />
...
</Routes>
// MyPage1.jsx
import { useLoadingContext } from "react-router-loading";
const loadingContext = useLoadingContext();
const loading = async () => {
// fetching data
// call method to indicate that fetching is done and we are ready to switch pages
loadingContext.done();
};
write a onClick function for your component
then function like this
import { useHistory } from "react-router-dom";
const history=useHistory();
const [loading,setLaoding]=React.useState(false);
const myfunction=async()=>{
setLoading(true);
const res= await fetch("your link here");
const data=res.json();
if(res.status===200)
{
console.log(succusfully fetch data)
setLoading(false);
history.push("/your_destination");
}
else{
setLoading(false);
console.log("error in fetch data")
}
}
write link like this
{loading?<Spin/> :
<p onClick={myfunction}>link</p>}

Next.js client side protected routes without server side rendering

I am a little bit confused about protected routes in next.js.
First of all, I don't want to use any server side rendering. I want to statically export
via next export. In that case, how do I implement client side protected routes?
Say, I have a back-end server with basic JWT authentication. How do I make certain routes protected from certain user and redirect them in /login page?
Since you're wanting to create protected routes with a static export, you'll need to do everything in the browser.
Verify their JWT in the browser
If their JWT is valid, render the page (including all requests to fetch data)
If their JWT is not valid, redirect them
For this, we're going to create a wrapper AuthCheck component.
Related:
How can you create a Private route in next.js?
AuthCheck
For verifying the JWT, you can use any method you'd like, including sending it to an api endpoint to verify it. Though I'm unsure if you can use Next.js api endpoints with static exports.
import { useRouter } from 'next/router'
export const AuthCheck = (props) => {
const router = useRouter()
const isJWTValid = useIsJWTValid() // you need to implement this. In this example, undefined means things are still loading, null means user is not signed in, anything truthy means they're signed in
if (typeof window !== 'undefined' && user === null) router.push('/')
if(!user) return <Loading /> // a loading component that prevents the page from rendering
return props.children
}
You can then add this to your app.js.
const MyApp = ({ Component, pageProps }) => {
return (
<AuthCheck>
<Component {...pageProps} />
</AuthCheck>
)
}
export default MyApp
Alternatively, you can also add this to any individual page. With this, you may need to debug the timing of any fetched data.
export default const ProtectedPage = () => {
return (
<AuthCheck>
<!-- contents of the page -->
</AuthCheck>
)
}

Component path prop is matched but is not rendered using client-only route in Gatsby

I'm trying to get Reach Router in Gatsby to navigate programmatically from one of my components. The URL is updated as expected however the route is not rendered and the Gatsby static routes list are displayed.
My code
<Router>
<PageTest1 default />
<PageTest2 path="/test2"/>
<PageTest3 path="/test3"/>
</Router>
The default component is renderd but not others.
How can I get it to render components?
You need to tell Gatsby about the routes so it knows which component to use to render those pages, as documented here.
// Implement the Gatsby API “onCreatePage”. This is
// called after every page is created.
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions
// Only update the `/app` page.
if (page.path.match(/^\/app/)) {
// page.matchPath is a special key that's used for matching pages
// with corresponding routes only on the client.
page.matchPath = "/app/*"
// Update the page.
createPage(page)
}
}

react router get full current path name

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.

Resources