Not really sure I'm doing wrong here. I have a header component which I am then using in my main app component where my "page" components are conditionally rendered based on the app. Manually going to the routes works, however React Router's Link component is not rendering the links as clickable buttons thus I can't click on anything...
Here is my header component:
function Header(props) {
const links = props.links.map(link => {
return (
<Link to={{pathname: link.path}} key={link.title}>{link.title}</Link>
);
});
return(
<Navbar className="border-bottom" bg="transparent" expand="lg">
<Navbar.Brand href="#home">Garrett Love</Navbar.Brand>
<Navbar.Toggle className="border-0" aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
{links}
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
I did try setting the to prop as both to={link.path} and to="/about" but neither worked.
I'm just putting this component in my main app component like so:
render() {
return(
<Router>
<Container className="p-0" fluid={true}>
<Header links={this.state.headerLinks} />
<Route path="/" exact render={() => <Home title={this.state.home.title} subTitle={this.state.home.subTitle} />} />
<Route path="/about" render={() => <About title={this.state.about.title} />} />
<Footer />
</Container>
</Router>
);
}
I see you has header component and some app component
But in your app component you show <Gbar /> and dont show <Header />
The best way to fix this:
In Header
const Header = props =>
<Navbar className="border-bottom" bg="transparent" expand="lg">
<Navbar.Brand href="#home">Garrett Love</Navbar.Brand>
<Navbar.Toggle className="border-0" aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
{props.links.map(link => <Link to={link.path} key={link.title}>{link.title}</Link>)}
</Nav>
</Navbar.Collapse>
</Navbar>
And in App:
render() {
return(
<Router>
<Container className="p-0" fluid={true}>
<Header links={this.state.headerLinks} />
<Route path="/" exact render={() => <Home title={this.state.home.title} subTitle={this.state.home.subTitle} />} />
<Route path="/about" render={() => <About title={this.state.about.title} />} />
<Footer />
</Container>
</Router>
);
}
Related
I am using react router dom to render a website with react and tailwindcss. The navbar when clicked refreshes and renders the component on it's own without the other components. This is not what I want.
I want the components rendered in a single page in the way it is structured in my App.js file
I have tried using normal hrefs and now Link from react-router-dom, But I still get the same result
App.js
const App = () => {
return (
<div className="max-w-[1440px] mx-auto bg-page overflow-hidden relative">
<Header />
<Routes>
<Route path="/" element={<Banner />} />
<Route path="/home" element={<Banner />} />
<Route path="/about" element={<About />} />
<Route path="/hero" element={<Hero />} />
<Route path="/featured" element={<Featured />} />
<Route path="/gallery" element={<GallerySection />} />
<Route path="/testimonies" element={<Testimony />} />
<Route path="/join" element={<Join />} />
<Route path="/footer" element={<Footer />} />
<Route path="/copy" element={<Copyright />} />
</Routes>
</div>
);
};
export default App;
Index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>
);
Navbar.js
const Nav = () => {
return (
<nav className="hidden lg:flex">
<ul className="flex gap-x-8 text-white">
{["home", "about", "featured", "gallery", "testimonies", "join"].map(
(item) => {
return (
<li key={`link-${item}`}>
<Link to={`/${item}`} className="capitalize">
{item}
</Link>
</li>
);
}
)}
</ul>
</nav>
);
};
export default Nav;
I would appreciate any help please
You need to use hashtags instead different routes.
So you have to use only one index route
<Route path="/" element={<IndexPage />} />
and render section components in IndexPage component one by one
const IndexPage = () => (
<>
<Banner />
...
</>
)
then add into each section component wrapper id attribute
const Banner = () => (
<div id="banner">
...content...
</div>
)
and use hashtag links in you Nav component:
<Link to={`#${item}`} className="capitalize">
{item}
</Link>
links will be looks like domain.com/#banner and if use open it then browser will scroll down to specific element with id
also I suggest to add some css to make scrolling smooth:
html {
scroll-behavior: smooth;
}
App.js
function App() {
<div className="App">
<Router>
<Switch>
<Route exact path="/home" component={Home} />
<Route exact path="/search" component={Home} />
</Switch>
</Router>
</div>;
}
Home.js
function Home() {
const location = useLocation();
return (
<div className="home">
<Component1 />
{location.pathname === "/home" && <Feed />}
{location.pathname === "/search" && <Search />}
<Component2 />
</div>
);
}
This works perfectly as I want to render the Feed or Search component depending on the URL.
But, I want to know is it okay to use location.pathname or is there any better alternative?
You could do something like:
App.js
function App() {
return <div className="App">
<Router>
<Switch>
<Route exact path="/home" component={() => <Home showFeed/>} />
<Route exact path="/search" component={() => <Home showSearch/>} />
</Switch>
</Router>
</div>;
}
Home.js
function Home(props) {
const location = useLocation();
return (
<div className="home">
<Component1 />
{props.showFeed && <Feed />}
{props.showSearch && <Search />}
<Component2 />
</div>
);
}
This allows you to abstract away the Home component's dependency on any routing mechanism, and simply allows you to control whether certain elements appear or not from outside this component.
use home component as layout. This can be highly recommended. You can rename your home component as Layout. This is more flexible way.
function Home() {
const location = useLocation();
return (
<div className="home">
<Component1 />
{ props.children }
<Component2 />
</div>
);
}
In your app.js modify like bellow
function App() {
<div className="App">
<Router>
<Switch>
<Route exact path="/home">
<Home>
<Feed />
</Home>
</Route>
<Route exact path="/search">
<Home>
<Search/>
</Home>
</Route>
</Route>
</Switch>
</Router>
</div>;
}
I am new to react development. And I want to implement the routing mechanism in my page.
For example, there's component contains routes with the <Home /> and <Login /> component.
function App() {
return (
<div className="App">
<Switch>
<Route exact path="/home">
<Home />
</Route>
<Route path="/login">
<Login />
</Route>
</Switch>
</div>
);
}
The <Home /> component contains a <Navbar /> and a <Switch /> with two <Route />:
Home.js
function Home() {
return (
<div>
<Navbar />
<div>
<Switch>
<Route exact path={`/home`}>
<Menu />
</Route>
<Route path={`/home/temperature`}>
<div>temperature</div>
</Route>
</Switch>
</div>
</div>
)
}
However, I defined the <Link /> in the <Menu /> component as below:
function Menu() {
return (
<div>
<li>
<Link to={`/home/temperature`}>temperature child page</Link>
</li>
</div>
)
}
Originally, the page would displayed the <Home /> component with <Menu /> and <div> temperature </div>
I expected that when I clicked the link (<Link to={/home/temperature}>temperature child page</Link>) then it would replace the <Menu /> component with the only the <div>temperature</div> (Dispalyed the <Navbar/> and <div>temperature</div>, but it could not display anything.
How should I correct it?
Solution:
I finally figure out why I cannot get child component in my js script.
Firstly, I need to wrap the <Switch> with <Router> in <App> component.
Then, by reference this , I realized that I should not specify the exact in <Route path="/home"> to make sure that the nested route can work as well.
function App() {
return (
<div className="App">
<Router>
<div>
<Switch>
<Route path="/home">
<Home />
</Route>
<Route path="/login">
<Login />
</Route>
</Switch>
</div>
</Router>
</div>
);
}
simple routing
<Router>
<Switch>
<Route path={"/home"} exact component={Home} />
</Switch>
</Router>
nested routing
<Router>
<Switch>
<Route path={"/home"} exact component={Home}
<Rout path={"/temperature"} exact component={Temperature} />
</Route>
</Switch>
</Router>
`
I create simple app and i try use in it react-router but i have problem.
When user click register or login the page should render necessary form but now to page change user must refresh page and then page change component i dont know why.
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'))
App class:
class App extends React.Component {
render() {
return (
<div className="App">
<Navbar/>
</div>
);
}
}
Navbar class:
class Navbar extends React.Component {
render(){
return (
<Nav bsStyle="tabs">
<LinkContainer to="/login" >
<NavItem >
LogIn
</NavItem>
</LinkContainer>
<LinkContainer to="/Register" >
<NavItem >
Register
</NavItem>
</LinkContainer>
<Router>
<BrowserRouter>
<Switch>
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
</Switch>
</BrowserRouter>
</Router>
</Nav>
)
}}
You will have to have your BrowserRouter as a top level component. The nav is the place which triggers what component has to be rendered.
ReactDOM.render(<App />, document.getElementById('root'));
App.js
class App extends React.Component {
render() {
return (
<div className="App">
<Navbar/>
<Router>
<BrowserRouter>
<Switch>
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
</Switch>
</BrowserRouter>
</Router>
</div>
);
}
}
Nav.js
class Navbar extends React.Component {
render(){
return (
<Nav bsStyle="tabs">
<LinkContainer to="/login" >
<NavItem >
LogIn
</NavItem>
</LinkContainer>
<LinkContainer to="/Register" >
<NavItem >
Register
</NavItem>
</LinkContainer>
</Nav>
)
}}
You have your Routing inside the Navbar component, that won't work.
Change your index.js to look like this:
ReactDOM.render((
<BrowserRouter>
<Switch>
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
<Route path="/" component={App} />
</Switch>
</BrowserRouter>
), document.getElementById('root'))
That should work, let me know if any issues. Also delete the BrowserRouter elements and children from Navbar
use BrowserRouter inside Router
<Router>
<BrowserRouter>
<Switch>
...
</Switch>
</BrowserRouter>
</Router>
I have problem with nested routing.
On the normal site I have other urls than on the / admin page and i have different design and html.
I prepared this sample routing but after the page refreshes, the page gets white without any error.
Can I ask for a consultation what did I do wrong?
APP COMPONENT
class App extends Component {
render() {
return (
<BrowserRouter>
<div className="container">
<Route exact path="/" render={(props) => (
<Page {...props} data={data} />
)} />
<Route exact path="/admin" render={(props) => (
<Admin {...props} data={data} />
)} />
</div>
</BrowserRouter>
);
}
}
PAGE COMPONENT
class Page extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Header />
<Route exact path="/" render={(props) => (
<Home {...props} videosJson={this.props.data} />
)} />
<Route path="/about" component={ About } />
<Route exact path="/video" render={(props) => (
<VideoGallery {...props} videosJson={this.props.data} />
)} />
<Route path="/video/:id" render={(props) => (
<VideoPage {...props} videosJson={this.props.data} />
)} />
<Route exact path="/photo" render={(props) => (
<PhotoGallery {...props} videosJson={this.props.data} />
)} />
<Route path="/photo/:id" render={(props) => (
<PhotoPage {...props} videosJson={this.props.data} />
)} />
<Route path="/contact" component={ Contact } />
<Footer />
</div>
</BrowserRouter>
)
}
}
ADMIN COMPONENT
class Admin extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Route exact path="/admin" render={(props) => (
<Dashboard {...props} />
)} />
</div>
</BrowserRouter>
)
}
}
Your React application which uses React-Router should only have one instance of a Router defined, as stated in the documentation:
The common low-level interface for all router components. Typically
apps will use one of the high-level routers instead
The error you are getting is because you are defining additional routers (in your case there are multiple instances of BrowserRouter) in your Page and Admin components.
Also some of your Routes are ambiguous e.g.
<Route exact path="/" render={(props) => (
<Page {...props} data={data} />
)} />
and:
<Route exact path="/" render={(props) => (
<Home {...props} videosJson={this.props.data} />
)} />
One Route says that root ('/') should navigate to the Page component, the other says that root should navigate to the Home component, hence there is a conflict. Make sure the routes are unique.
I change my approach to this situation but dont work. Url /admin load Header and Footer component although he should not and component Dashboard not load.
Any sugestion?
<BrowserRouter>
<div className="container">
<Page>
<Header />
<Route exact path="/" render={(props) => (
<Home {...props} videosJson={data} />
)} />
<Route path="/about" component={ About } />
<Route exact path="/video" render={(props) => (
<VideoGallery {...props} videosJson={data} />
)} />
<Route path="/video/:id" render={(props) => (
<VideoPage {...props} videosJson={data} />
)} />
<Route exact path="/photo" render={(props) => (
<PhotoGallery {...props} videosJson={data} />
)} />
<Route path="/photo/:id" render={(props) => (
<PhotoPage {...props} videosJson={data} />
)} />
<Route path="/contact" component={ Contact } />
<Footer />
</Page>
<Admin>
<Route exact path="/admin" render={(props) => (
<Dashboard />
)} />
</Admin>
</div>
</BrowserRouter>
Admin Component:
class Admin extends React.Component {
render() {
console.log("ADMIN:", this.props);
return (
<div className="row">
<h1>ADMIN</h1>
{this.props.children}
</div>
)
}
}
Page Component:
class Page extends React.Component {
render() {
console.log("PAGE:", this.props);
return (
<div>
{this.props.children}
</div>
)
}
}