I'm having an issue making a link to an external page in React.
My app uses react-router-dom and i have my App.js like this:
function App() {
return (
<Provider store={store}>
<ReactReduxFirebaseProvider {...rrfProps}>
<div className="App my-content">
<Router>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/accommodations" component={Accommodations} />
<Route exact path="/rentals" component={RentalServices} />
<Route exact path="/tours" component={DailyTours} />
<Route exact path="/contacts" component={ContactUs} />
<Route
exact
path="/editaccommodations"
component={EditAccommodations}
/>
<Route
exact
path="/addaccommodation"
component={AddAccommodation}
/>
<Route
exact
path="/accommodations/:id"
component={AccommodationPage}
/>
<Route component={NotFound} />
</Switch>
<Footer />
</Router>
</div>
</ReactReduxFirebaseProvider>
</Provider>
);
}
In my AccommodationPage i have a link to an external page
<ul className="booking-sites p-0">
{accommodations && accommodation.bookings.map((booking, index) => {
return (
<li key={index} className="booking-method">
<a href={booking.link} className="booking-link">
<img
src={booking.logo}
alt={`booking method ${index}`}
className="booking-icon"
/>
</a>
</li>
);
})}
</ul>
booking.link is for example "www.foo.com"
When i click on the link, instead of opening "www.foo.com" it opens "http://localhost:3000/accommodations/www.foo.com"
You can do this by using Link as below. (Replace the a tag with this)
<Link to={{ pathname: booking.link }} />
Also, If you want to open the link in a new tab just simply add target="_blank".
Try changing the booking.link so that it is like http://www.example.com. Include the http://.
the suggestions you gave me seemed not to work so i played a bit with it and while trying to add the http:// from the component (just for a trial) i found the solution:
<a href={`${booking.link}`} className="booking-link">
<img
src={booking.logo}
alt={`booking method ${index}`}
className="booking-icon"
/>
</a>
But i didn't really understand what happened... do you know why now it works?
Related
I have set up a login page for my web app but the site header component I created earlier appears on the top. It has a menu in it that leads to other pages, so if it's on the login page a user doesn't need to login when they can just click the menu option that will lead them to the home page.
I would like the site header to be invisible on the login, register and reset pages.
index.js
return (
<BrowserRouter>
<SiteHeader />
<Routes>
<Route path="/reviews/:id" element={ <MovieReviewPage /> } />
<Route path="/movies/home" element={<HomePage />} />
<Route path="/movies/favorites" element={<FavoriteMoviesPage />} />
<Route path="/movies/upcoming" element={<UpcomingMoviesPage />} />
<Route path="/movies/:id" element={<MoviePage />} />
<Route exact path="/" element={<LoginPage />} />
<Route exact path="/register" element={<RegisterPage />} />
<Route exact path="/reset" element={<ResetPage />} />
<Route path="*" element={ <Navigate to="/" /> } />
</Routes>
</BrowserRouter>
);
};
There are many ways to do that, but personally, I prefer to do so.
export const MyLayout = ({children}) => {
return (
<>
<SiteHeader />
{children}
</>
)
}
And after all, put your PageComponent inside component wherever you need.
For example.
const HomePage = () => {
return (
<MyLayout>
<div> This is Home Page </div>
</MyLayout>
)
}
Add an Authentication Context Provider. You could then read the context and render the header when you're logged in, else not.
https://codesandbox.io/embed/authentication-with-react-context-d3x0r
In my app.js, I have a list of Routes:-
<Switch>
<Route path='/:locale'>
<Header />
<Container />
<Footer />
</Route>
<Route path='/notfound' component={NotFound} />
<Redirect to='/notfound' />
</Switch>
I have a URL like www.mydomainname.com/us. I want the first route to render the components only when the :locale matches us or uk. If the :locale is empty or something not equal to us or uk (like au), then the page should route to /notfound.
The problem I am currently facing is, if I enter www.mydomainname.com/notfound or any random stuff after www.mydomainname.com/, then the first route is executing. I know I can get the :locale using useParams(), but how do I check it against an array of allowed values and reroute to the /notfound page if the check fails?
The route "/:locale" is a catch all route, so it will match any "/randomstring". Introduce a component Body which is a locale specific renderer.
<Switch>
<Route path='/notfound' component={NotFound} />
<Route path='/:locale'>
<Body>
<Header />
<Container />
<Footer />
<Body>
</Route>
<Redirect from='/' to='/notfound' exact />
</Switch>
And Body component will be handling redirect
const Body = (props) => {
const { locale } = useParams()
if (["us", "uk"].indexOf(locale) != -1)
return(props.children)
else
return(
<Redirect to="/notfound" />
)
}
The react-router-dom#5 Route component's path prop uses path-to-regexp under the hood, so you can use this to more exactly match paths. path="/:locale(us|uk)" will only match "/us" and "/uk" paths.
Example:
<Switch>
<Route path="/:locale(us|uk)">
<Header />
<Container />
<Footer />
</Route>
<Route path="/notfound" component={NotFound} />
<Redirect to="/notfound" />
</Switch>
I need some help to accomplish routing in ReactJS.
I describe my problem and hope you can help me..
I have famous index.js in this file and I call app.js from it
**index.js**
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('app')
);
inside app.js I wrote some code for routing as below :
**App.js**
return (
<div>
{message &&
<div className={`alert ${type}`}>{message}</div>
}
<Router history={history}>
<div>
<PrivateRoute exact path="/" component={Main} />
<Route path="/login" component={SignIn} />
</div>
</Router>
</div>
);
this work correctly and after login I redirect to Main.js
and now my problem :
I`ve written some route in Main.js page that all other pages must inherit from that. I mean all other page must have the skeleton of Main.js
here is some code of Main.js
**Main.js**
<main className={classes.content}>
<Link to="/HomePage"> HomePage</Link>
<Link to="/Admin"> Admin </Link>
<Link to="/Menus"> Menu </Link>
<Link to="/Product"> Product </Link>
<div className={classes.appBarSpacer} />
<Switch>
<PrivateRoute path="/HomePage" component={HomePage} />
<PrivateRoute path="/Admin" component={Admin} />
<PrivateRoute path="/Menus" component={Menus} />
<PrivateRoute path="/Product" component={Product} />
</Switch>
</main>
unfortunately none of this routes works..
I`m extremely confused because all of things seems right
Issue
None of your nested paths are an exact match to "/" rendered by the PrivateRoute of the main router, so they are not rendered.
Solution
Place the parent routes in a Switch and reorder the routes so the "/login" path can be matched before the more general "/" path. Remove the exact prop from the "/" path.
App.js
return (
<div>
{message &&
<div className={`alert ${type}`}>{message}</div>
}
<Router history={history}>
<Switch>
<Route path="/login" component={SignIn} />
<PrivateRoute path="/" component={Main} />
</Switch>
</Router>
</div>
);
Main.js
<main className={classes.content}>
<Link to="/HomePage"> HomePage</Link>
<Link to="/Admin"> Admin </Link>
<Link to="/Menus"> Menu </Link>
<Link to="/Product"> Product </Link>
<div className={classes.appBarSpacer} />
<Switch>
<PrivateRoute path="/HomePage" component={HomePage} />
<PrivateRoute path="/Admin" component={Admin} />
<PrivateRoute path="/Menus" component={Menus} />
<PrivateRoute path="/Product" component={Product} />
</Switch>
</main>
consider the following example, I have a login page and an admin page. After logging in we will be redirected to admin page.
The admin page is shown as follows.
Desired behaviour: To render cars component in the admin component itself
Actual behaviour: On clicking cars or bikes component they are being rendered on a different page.
code is as follows
App.js
//imports here
function App() {
return(
<Router>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/admin" component={Admin} />
<Route exact path="/cars" component={Cars} />
<Route exact path="/bikes" component={Bikes} />
</Switch>
</Router>
);
}
Admin.js
//imports here
const Admin = () => {
return (
<Fragment>
<div className="is-flex">
<Sidebar />
<Navbar />
</div>
</Fragment>
);
};
navbar.js
// imports here
const Sidebar = () => {
return (
<aside className="aside">
<p className="menu-label">Test Routes</p>
<ul className="menu-list">
<li>
<Link to="/cars">Cars</Link>
</li>
<li>
<Link to="/bikes">Bikes</Link>
</li>
</ul>
</aside>
);
};
Using react-router-dom ^5.1.2
Tried this but not able to understand what I missed? how to solve this problem?
Move your default route to the bottom of the stack. i.e.
function App() {
return(
<Router>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/cars" component={Cars} />
<Route path="/bikes" component={Bikes} />
<Route exact path="/" component={Login} />
</Switch>
</Router>
);
}
I have a react application in which I have wrapped layout components for the other routes, the thing is when I click the links present in the sidebar(part of layout) they are not being rendered on the screen, here is my code.
App.js
//Imports here
<Provider store={store}>
<Router>
<Switch>
<Layout>
<Route exact path="/admin" render={() => <Admin />} />
<Route exact path="/employees" render={() => <Employees />} />
<Route exact path="/profile" component={Profile} />
</Layout>
<Switch>
</Router>
</Provider>
Layout.js
//imports here
//styling here
<Link to='/employees' />
// and likewise for rest of the routes
When clicking the links ie, employees or profile they aren't being rendered, tried console.log to see if my layout was obstructing that, but no use. Please help me
It should be inside the Switch component but you can wrap it with a Layout component like that.
const Headers = () => (
<Layout>
<ul>
<li>
<Link to="/admin">Admin</Link>
</li>
<li>
<Link to="/profile">Profile</Link>
</li>
<li>
<Link to="/employees">Employees</Link>
</li>
</ul>
</Layout>
);
function App() {
return (
<Router>
<Layout>
<Header></Header>
<Switch>
<Route exact path="/admin" render={() => <Admin />} />
<Route exact path="/employees" render={() => <Employees/>}/>
<Route exact path="/profile" component={Profile} />
</Switch>
</Layout>
</Router>
);
}
If your URL is changing but the content is not being rendered, the problem is this, apart from wrapping the Routes as mentioned in #G.aziz 's answer since the routes are children WRT layout components we have to use {props.children} inside the layout component to render the content like so...
Layout.jsx
<div>
<Sidebar />
<Navbar />
{props.children} // here we are rendering the routes which we mentioned in the switch component in App.js
</div>
For me this solution fixed. Also please refer this question for further information. React-router v4, URL changing but component doesn't render