React Router Navigate Issue in Semantic Ui React - javascript

I have an issue with navigating pages via Route.
I used semantic ui react components to handle with the issue.
When I link any item in navbar, the url is changed like http://localhost:3000/ to http://localhost:3000/list but the relevant component page cannot open.
How can I fix it?
Here is my index.js code shown below.
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter> ,
document.getElementById('root')
);
Here is my App.js code shown below.
function App() {
return (
<div className="App">
<Container style={{"marginTop": "20px"}}>
<Header />
<Route path="/">
<AccordionComponent items={items} />
</Route>
<Route path="/list">
<Search />
</Route>
<Route path="/dropdown">
<DropdownForm options={options}/>;
</Route>
<Route path="/translate">
<Translate />
</Route>
</Container>
</div>
);
}
export default App;
Here is my Route Component shown below.
const Route = ({ path, children }) => {
return window.location.pathname === path ? children : null;
};
export default Route;
Here is my Header Component shown below.
import React, { useState } from 'react';
import { Menu } from 'semantic-ui-react'
import { Link } from "react-router-dom";
const Header = () => {
const [activeItem, setActiveItem] = useState('Accordion');
const handleItemClick = (name) => setActiveItem(name)
return (
<Menu secondary pointing>
<Menu.Item
as={Link} to="/"
name='Accordion'
active={activeItem === 'Accordion'}
onClick={() => handleItemClick('Accordion')}
/>
<Menu.Item
as={Link} to="/list"
name='Search'
active={activeItem === 'Search'}
onClick={() => handleItemClick('Search')}
/>
<Menu.Item
as={Link} to="/dropdown"
name='Dropdown'
active={activeItem === 'Dropdown'}
onClick={() => handleItemClick('Dropdown')}
/>
<Menu.Item
as={Link} to="/translate"
name='Translate'
active={activeItem === 'Translate'}
onClick={() => handleItemClick('Translate')}
/>
</Menu>
);
};
export default Header;

Wrap de routes with Switch as this example:
function App() {
return (
<div className="App">
<Container style={{"marginTop": "20px"}}>
<Header />
<Switch>
<Route path="/">
<AccordionComponent items={items} />
</Route>
<Route path="/list">
<Search />
</Route>
<Route path="/dropdown">
<DropdownForm options={options}/>;
</Route>
<Route path="/translate">
<Translate />
</Route>
</Switch>
</Container>
</div>
);
}
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Docs: https://reactrouter.com/web/api/Switch

Related

React navbar renders components separately with react-router-dom

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;
}

How to hide Footer component for some pages in react

i would like to hide footer component in some page
app.js
<div className="App">
<Header setShowMenu={setShowMenu} />
{showMenu ? <Menu navigateTo={navigateTo} setShowMenu={setShowMenu} /> : null}
<Main navigateTo={navigateTo} />
<Footer navigateTo={navigateTo} />
</div>
main.jsx
<div>
<Routes>
<Route path="/" element={<HomePage navigateTo={navigateTo} />} />
<Route path="/precard" element={<PreCard />} />
<Route path="/order" element={<Order />} />
<Route path="/contact" element={<Contact />} />
<Route path="/thankspage" element={<ThanksPage navigateTo={navigateTo}/>} />
<Route path="/*" element={<HomePage />} />
</Routes>
</div>
Note: The Router in index.js
So I want to hide the footer in ./order Page
I hope you guys have solution for me :)
You can use useLocation() hook to check the route path in the <Footer /> component and based on the pathname you can render the <Footer /> component.
Example :
import React from "react";
import { useLocation } from "react-router-dom";
const Footer = () => {
const { pathname } = useLocation();
console.log(pathname);
// you can check a more conditions here
if (pathname === "/thanks") return null;
return <div className="footer">Footer</div>;
};
export { Footer };
App.js
import { Route, Switch, BrowserRouter } from "react-router-dom";
import "./styles.css";
import { Home } from "./pages/Home";
import { Catalog } from "./pages/Catalog";
import { Thanks } from "./pages/Thanks";
import { Header } from "./components/Header";
import { Footer } from "./components/Footer";
import { Page404 } from "./pages/Page404";
const App = () => {
return (
<>
<BrowserRouter>
<Header />
<Switch>
<Route path={"/"} exact>
<Home />
</Route>
<Route path={"/catalog"} exact>
<Catalog />
</Route>
<Route path={"/thanks"} exact>
<Thanks />
</Route>
<Route path={"*"}>
<Page404 />
</Route>
{/* <Redirect to={'/'} /> */}
</Switch>
<Footer />
</BrowserRouter>
</>
);
};
export { App };

Render specific react component based on the URL

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>;
}

how to render different components using react-router-dom v6.0.0 with react-redux

i am trying to render different components by clicking on a link but the problem is the url updates and the ui remains same unchanged, everytime i click on different item to render but the same thing happens, i tried a lot to fix it but i can not find a solution for this.
starting from index.js as entry point
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import store from "./Components/store";
import { Provider } from "react-redux";
import "./index.css";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</StrictMode>,
rootElement
);
then App.js to render components
import "./App.css";
import { Routes, Route } from "react-router-dom";
import { SingleTodoPage } from "./Components/SingleTodoPage";
import { EditTodo } from "./Components/EditTodo";
import { Home } from "./Components/Home";
function App() {
return (
<Routes>
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Route path="/" element={<Home />} />
<Route path="todo/:todoId" element={<SingleTodoPage />} />
<Route path="edit/:todoId" element={<EditTodo />} />
</div>
</div>
</Routes>
);
}
export default App;
SingleTodo where linking different components
<SingleTodo />
<List>
{todos.map((todo) => (
<ListItem key={todo.id} className={classes.listRoot}>
<ListItemText primary={todo.name} />
<ListItemSecondaryAction>
<CheckBoxIcon color="primary" />
<DeleteIcon color="secondary" />
<Link to={`edit/${todo.id}`} className="button">
<EditIcon />
</Link>
<Link to={`todo/${todo.id}`}>view</Link>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
codesandbox for more details, i am using useParams hook in SingleTodo and in EditTodo
to get dynamic url params.
please if anyone knows how to solve this please help me...thanks
Move the non-routing-related elements out of the Routes component.
function App() {
return (
<Routes>
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Route path="/" element={<Home />} />
<Route path="todo/:todoId" element={<SingleTodoPage />} />
<Route path="edit/:todoId" element={<EditTodo />} />
</div>
</div>
</Routes>
);
}
To this
function App() {
return (
<div>
<div className="header-text">Todo List</div>
<div className="box">
<Routes>
<Route path="/" element={<Home />} />
<Route path="todo/:todoId" element={<SingleTodoPage />} />
<Route path="edit/:todoId" element={<EditTodo />} />
</Routes>
</div>
</div>
);
}
The Routes component functions largely as the replacement for react-router-dom v4/5's Switch component.

Reactjs - props not changing during Routing

I have a BrowserRouter which renders different components based on the Route. Most, of these components have similar markup.
So, I created a Wrapper component which will recieve props, and render its {children} if provided. This Wrapper is called in Route's.
import React, {Component} from 'react'
import Context from '../../provider'
import {
BrowserRouter,
Route,
Redirect,
Switch,
} from "react-router-dom"
import {
Container,
Row,
Col,
} from 'reactstrap'
import Profile from './ContentComponent/Profile'
import Subreddit from './ContentComponent/Subreddit'
import PostExpanded from './ContentComponent/PostExpanded'
import InfoComponent from './InfoComponent'
import SwitchTab from './ContentComponent/Subreddit/SwitchTab'
import NewPost from './ContentComponent/assets/NewPost'
import './style.css'
class Wrapper extends React.Component {
componentDidMount() {
this.props.setActiveTab(this.props.activeTab);
}
render() {
{console.log('Wrapper props: ', this.props)}
return (
<Row>
<Col md='8' id='content-block'>
<SwitchTab />
{this.props.children}
</Col>
<Col md='4' id='info-block'>
<InfoComponent info={this.props.info} {...this.props}/>
</Col>
</Row>
)
}
}
export default class BodyComponent extends Component {
render() {
return (
<BrowserRouter>
<Context.Consumer>
{context => {
return (
<Container>
<Switch>
<Route
exact
path='/'
render={() =>
<Redirect to='r/home/' />
}
/>
<Route
exact
path='/r/home/'
render={() =>
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'1'}
info='home'
/>
}
/>
<Route
exact
path='/r/popular/'
render={() =>
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'2'}
info='popular'
/>
}
/>
<Route
exact
path='/r/all/'
render={() =>
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'3'}
info='all'
/>
}
/>
<Route
exact
path='/u/:username/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='user'
user={props.match.params.username}
>
<Profile username={props.match.params.username} />
</Wrapper>
)
}}
/>
<Route
exact
path = '/r/:subreddit/new/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='subreddit'
subreddit={props.match.params.subreddit}
>
<NewPost />
</Wrapper>
)
}}
/>
<Route
exact
path = '/r/:subreddit/post/:postid/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='subreddit'
subreddit={props.match.params.subreddit}
>
<PostExpanded
subreddit={props.match.params.subreddit}
postid={props.match.params.postid}
/>
</Wrapper>
)
}}
/>
<Route
exact
path='/r/:subreddit/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='subreddit'
subreddit={props.match.params.subreddit}
>
<Subreddit subreddit={props.match.params.subreddit} />
</Wrapper>
)
}}
/>
<Route
exact
path = '/new/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='new'
>
<NewPost />
</Wrapper>
)
}}
/>
</Switch>
</Container>
)
}}
</Context.Consumer>
</BrowserRouter>
)
}
}
I am facing multiple problems here and I think they can all be fixed at once, I don't know how?
The Wrapper props are not getting changed when I am changing the URL
using props.history.push:
<NavItem>
<NavLink
className={classnames({ active: context.activeTab === '1' })}
onClick={() =>{
context.toggleTab('1');
this.props.history.push('/r/home/')
}}
>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: context.activeTab === '2' })}
onClick={() => {
context.toggleTab('2');
this.props.history.push('/r/popular/')
}}
>
Popular
</NavLink>
</NavItem>
I think I got the problem while going through my code. So, the problem started when I wanted to use props.history.push in my HeaderComponent. I was getting error so I wrapped it with BrowserRouter and exported withRouter() which enabled me to use props.history.push
So, unknowingly I have created 2 BrowserRouter's:
<React.Fragment>
<BrowserRouter>
<NavbarComponent />
<TabComponent />
</BrowserRouter>
<BrowserRouter>
<Switch>
<Route ... />
<Route ... />
</Switch>
</BroserRouter>
</React.Fragment>
So, I was changing URLs in TabComponent and expecting that to change my Route's and modify content.
Having a global BrowserRouter (don't think that global's the right word but) solved the problem.
<React.Fragment>
<BrowserRouter>
<NavbarComponent />
<TabComponent />
<Switch>
<Route ... />
<Route ... />
</Switch>
</BroserRouter>
</React.Fragment>

Categories