Using material ui tabs with react router? - javascript

I have a project in react/typescript. I have a react router that looks like this
const Root = () => (
<>
<NavBar/>
<Router>
<Route path="/" component={Home} />
<Route path="/timer" component={TimerPage} />
</Router>
</>
);
And I have a material-ui appbar that looks like this
export default function NavBar() {
return (
<div>
<AppBar position="static">
<Tabs>
<Tab label="Timer" to="/timer" component={TimerPage} />
</Tabs>
</AppBar>
</div>
);
}
There are a few issues - first the 'to' in Tab doesn't compile. Secondly, how do I make these two components work together, given they do very similar things?

If you are trying to navigate to another page, wrap your tab component, let react-router handle with the navigation and navigate using react-router history,
<Tabs value={value} onChange={handleChange} aria-label="simple tabs
example">
<div onClick={() => history.push("/timer")}>
<Tab label="Timer" />
</div>
</Tabs>

<Router>
<Route path="/" component={Home} />
<Route path="/timer" component={TimerPage} />
</Router>
Route should be inside Switch. Also, if you write path="/" this means that whatever page you will visit will still go to "home" page. This is because react-router does something like "least" checking of routes. So, if you had defined path "/images", before "/images/1", both will route you to "/images". Instead you could change the order of these paths, or add exact keyword before the first one.
Take a look at example below.
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/timer" component={TimerPage} />
</Switch>
</Router>
or
<Router>
<Switch>
<Route path="/timer" component={TimerPage} />
<Route path="/" component={Home} />
</Switch>
</Router>
As for your second issue, you should put your AppBar (or div or any container) inside Router and assign Link to component property of Tab:
<Router>
<AppBar position="static">
<Tabs>
<Tab label="Timer" to="/timer" component={Link} />
</Tabs>
</AppBar>
</Router>
Keep in mind that Link component is imported from react-router and not from #mui.

Related

How to remove a site header from specific pages React

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

Nested Routing not working in react-router version 6 [duplicate]

I was refactoring my React app after updating React Router to v6 and I got rid of the error I was getting in my routes, except now the desired layout is broken.
I need to include a permanent toolbar and a sidebar to be visible only in some pages. I tried to follow the docs but now the layout component is placed above all the pages it should be wrapping, not just overlapping them, but actually concealing them behind it.
The Layout component:
function Layout({ children }) {
return (
<div className="layout">
<Header />
<SidePanel />
<div className="main" style={{ marginTop: "100px" }}>
{children}
</div>
</div>
);
}
export default Layout;
The AppRouter component:
function AppRouter() {
return (
<Router>
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/sign-up" element={<SignUp />} />
<Route element={<Layout />}>
<Route path="/diary" element={<Diary />} />
<Route path="/results" element={<Results />} />
<Route path="/details" element={<Details />} />
<Route path="/about" element={<About />} />
</Route>
</Routes>
</Router>
);
}
export default AppRouter;
Layout should render an Outlet for the children Routes to be rendered into.
import { Outlet } from 'react-router-dom';
function Layout() {
return (
<div className="layout">
<Header />
<SidePanel />
<div className="main" style={{ marginTop: "100px" }}>
<Outlet />
</div>
</div>
);
}
Outlet
An <Outlet> should be used in parent route elements to render their
child route elements. This allows nested UI to show up when child
routes are rendered.

ReactJS Routing Page Refresh

Currently using ReactJS to construct a small web app. I have the following parent function:
const Main = () => {
return (
<div className="dialog-base">
<BrowserRouter>
<Switch>
<Route exact path="/login" component={Login}></Route>
<Route exact path="/login/forgot_password" component={ForgotPwd}></Route>
<Route exact path="/login/reset_password/:key" component={ResetPwd}></Route>
<Route exact path="/portal" component={Portal}></Route>
</Switch>
</BrowserRouter>
</div>
);
}
and the following is the "Portal" component:
class Portal extends React.Component {
render = () => {
return (
<BrowserRouter basename="/main">
<div className="navmenu">
<NavLink to="messaging" activeClassName="selected">Messaging</NavLink>
<NavLink to="files" activeClassName="selected"></NavLink>
<NavLink to="payledger" activeClassName="selected"></NavLink>
</div>
<div className="apparea">
<Switch>
<Route path="/messaging" component={Messaging}></Route>
<Route path="/files" component={Files}></Route>
<Route path="/payledger" component={PayLedger}></Route>
</Switch>
</div>
</BrowserRouter>
);
}
}
When the portal component is loaded and I refresh the web page, the page goes blank. I am assuming that this has something to do with the nested routing? Any help on how to fix it would be much appreciated.
You don't need two <BrowserRouter />. Just define one <BrowserRouter /> in your top level component.
In react-router-dom v4+ the <Route /> is just like a regular component and you can use it inside your components to render UI when the path matches the URL.
Here is the working codesandbox example.
Make sure not to put exact on your parent <Route /> because when you have child routes like /main/messaging the <Route exact path="/main" /> never gets to render and therefore children of that route can't be rendered also.
You keep your <Main /> component as is but remove the exact from the <Route path='/portal' /> and change the <Portal />.
class Portal extends React.Component {
render = () => {
return (
<React.Fragment>
<div className="navmenu">
<NavLink to="/portal/messaging" activeClassName="selected">Messaging</NavLink>
<NavLink to="/portal/files" activeClassName="selected"></NavLink>
<NavLink to="/portal/payledger" activeClassName="selected"></NavLink>
</div>
<div className="apparea">
<Switch>
<Route path="/portal/messaging" component={Messaging}></Route>
<Route path="/portal/files" component={Files}></Route>
<Route path="/portal/payledger" component={PayLedger}></Route>
</Switch>
</div>
</React.Fragment>
);
}
}

React: how to declare routes inside a component?

First off, I tried searching for this issue before I posted but couldn't find a solution for a similar use case.
So I have a component called App.js where I define all my top level routes:
<TransitionGroup>
<CSSTransition key={location.key} mountOnEnter={true} unMountOnExit={true} timeout={800} classNames="fade-up-down">
<Switch location={location}>
<Route exact path="/" component={Home} />
<Route exact path="/about" component={About} />
<Route exact path="/artists" component={Artists} />
<Route path="/artworks/:slug" component={Artwork} />
</Switch>
</CSSTransition>
</TransitionGroup>
Now, inside the home component, I want to have my second level of routes, which I didn't do in App.js because I had props to pass from Home.js to the child components. The routes portion in my Home.js looks like this:
<Switch>
<Route exact path="/" render={(props) => <Map {...props} artworks={artworks} />} />
<Route exact path="/grid" render={(props) => <Grid {...props} artworks={artworks} />} />
<Route exact path="/rainbow" render={(props) => <Rainbow {...props} artworks={artworks} />} />
</Switch>
The second level routes inside Home.js work fine, but when I try to go to any of the other top level routes, eg. /artists/ or /about, they do not work.
Can someone please point me to the right direction here? Thanks!
I don't think is it possible the way you want.
I think you are overriding the App Router when you navigate to you Home component.
Your routes has to be on a top lvl of your App
Moving the routes after the first one from to the top worked. Here's how it looks now:
<TransitionGroup>
<CSSTransition key={location.key} mountOnEnter={true} unMountOnExit={true} timeout={800} classNames="fade-up-down">
<Switch location={location}>
<Route exact path="/about" component={About} />
<Route exact path="/artists" component={Artists} />
<Route path="/artworks/:slug" component={Artwork} />
<Route path="/" component={Home} />
</Switch>
</CSSTransition>
</TransitionGroup>

Unable to render react components upon clicking the Links

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

Categories

Resources