React router 4 how to nested routes /admin and / - javascript

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

Related

React-router outlet confusion

Why my outlet is not working in react-router-dom. All my components worked fine until I use Outlet and after using outlet my navigation component is not showing while other component seems to render.
import Home from "./Routes/Home/Home.component";
import { Routes, Route, Outlet } from "react-router-dom";
const Navigation = () => {
return (
<div>
<div>
<h1>Hello I am Navigation!!!</h1>
</div>
<Outlet />
</div>
);
};
const Shop = () => {
return <h2>I am shop component</h2>
}
const App = () => {
return (
<Routes>
<Route path='/' element={<Navigation />} />
<Route index element={<Home />} />
<Route path='shop' element={<Shop />} />
</Routes>
);
};
export default App;
I am receiving this:
enter image description here
and I want navigation component to render all above and persist every time I navigate to elsewhere.
for using of Outlet you need Add children to Route Component
const App = () => {
return (
<Routes>
<Route path='/' element={<Navigation/>}>
<Route path="url1" element{<ChildElemnt1 />} />
<Route path="url2" element{<ChildElemnt2 />} />
<Route path="url3" element{<ChildElemnt3 />} />
...
</Route>
<Route index element={<Home />} />
<Route path='shop' element={<Shop/>}/>
</Routes>
);
};
The Navigation component isn't rendered as a layout route with nested routes, so nothing is rendered into the Outlet it is rendering. Navigation will also only render on path "/".
If you want the Navigation component to render always then you can render it alone outside the routes.
const Navigation = () => {
return (
<div>
<div>
<h1>Hello I am Navigation!!!</h1>
</div>
</div>
);
};
const App = () => {
return (
<>
<Navigation />
<Routes>
<Route path='/'>
<Route index element={<Home />} />
<Route path='shop' element={<Shop />} />
</Route>
</Routes>
</>
);
};
Or you can utilize it as a layout route such that it wraps nested routes that render their element into the Outlet.
const Navigation = () => {
return (
<div>
<div>
<h1>Hello I am Navigation!!!</h1>
</div>
<Outlet />
</div>
);
};
const App = () => {
return (
<Routes>
<Route path='/' element={<Navigation />} />
<Route index element={<Home />} />
<Route path='shop' element={<Shop />} />
</Route>
</Routes>
);
};

How to 1). put a div , 2). render a component without Route inside <Routes> with React Router in v6 React?

I want to put a div inside <Routes> and also Render a <Topbar /> and <Sidebar /> component inside <Routes> without <Route> tag for them.
My code is as follows:-
const App = () => {
return (
<Router>
<Routes>
<Route path="login" element={<Login />} />
<Topbar />
<div className="container">
<Sidebar />
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</div>
</Routes>
</Router>
);
};
I want to implement <Topbar /> and <Sidebar /> for all the routes.
But for an exception of login Page (Topbar and Sidebar should not be shown on the login page).
That's why I had put login Route at the top of Topbar and Sidebar.
The console is showing error as:
Uncaught Error: [Topbar] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
How to implement this functionality?
In react-router-dom v6 only Route and React.Fragment components are valid children for the Routes component.
Use layout components to render the Topbar and Sidebar components along with an Outlet for nested routes for the routes you want to render these components.
Example:
import { Routes, Route, Outlet } from 'react-router-dom';
const Layout = () => (
<>
<Topbar />
<div className="container">
<Sidebar />
<Outlet />
</div>
</>
);
const App = () => {
return (
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</Route>
</Routes>
</Router>
);
};
Change your routes like below,
you need to check whether user is logged in or not, if user logged in use Tobbar, Sidebar etc, otherwise just return login route
const App = () => {
const [isLogin, setIsLogin] = useState(false)
return (
<Router>
<Routes>
{ isLogin ? <Topbar />
<div className="container">
<Sidebar />
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</div> : <Route path="login" element={<Login />} />
</Routes>
</Router>
);
};

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

React loadable issues

So the problem I am facing is this. When I load the page, the stylings of the Header component are not being rendered, but when I remove the load Logic they are. The problem might lie in Header component BCS it is in every Route except Login. I need it to be rendered on every path except Login. Where the error could be?
const Cart = loadable(
() =>
new Promise((resolve, reject) =>
setTimeout(() => resolve(import("./components/Cart/Cart")), 100)
),
{
fallback: <div className="login__loader">
<img src='./audie/Glowing ring.gif' alt= ''></img>
</div>
}
);
const Book = loadable(
() =>
new Promise((resolve, reject) =>
setTimeout(() => resolve(import('./components/Home/Book')), 100)
),
{
fallback: <div>Loading...</div>
}
);
const App=()=> {
return (
<React.Fragment>
<Switch>
<Route exact path='/'>
<Header />
<Home />
</Route>
<Route path="/cart">
<Header />
<Cart />
</Route>
<Route path="/stripecontainer">
<Header />
<StripeContainer />
</Route>
<Route path='/book/:bookId'>
<Header />
<Book />
</Route>
<Route path='books'>
<Books/>
</Route>
<Route path='/forgotpassword'>
<ForgotPassword />
</Route>
<Route path='/passwordreset/:resetToken'>
<ResetPassword />
</Route>
<Route exact path='/register'>
<Register />
</Route>
<Route path='/login'>
<Login />
</Route>
</Switch>
</React.Fragment>
);
}
export default App
So the problem was in CSS.
Styles from Header.css needed to be in App.css. I don't know why

react-router-dom redirect not redirecting to the component I want it to but it is redirecting to a different path

Versions
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.0",
"react-router-dom": "^5.2.0",
I have an issue where my conditional Redirect component is not working as it should. Is it because it's outside of the Switch component. I want it to redirect to the /error route if apiError is true. The conditional works since I tested with just the Error component and not the error route. The Redirect component also works since the path does change but the component is not rendered.
render() {
const { currentUser, isLoaded, apiError } = this.state;
return (
<Router>
{currentUser ? (
<div className='App'>
<Switch>
<Route exact path='/title/:id' render={props => <ShowTitle {...props} /> } />
<Route exact path='/shuffle' render={props => <Titles {...props} isLoaded={isLoaded} /> } />
<Route exact path='/about' render={props => <About {...props} /> } />
<Route exact path='/all-titles' render={props => <Titles {...props} isLoaded={isLoaded} /> } />
<Route exact path='/error' render={props => <Error {...props} />} />
<Route exact path='/' render={props => <Redirect to={'/' + currentUser.viewType} /> } />
<Route exact path='/logout' component={Logout} />
<Redirect to='/all-titles' />
</Switch>
</div>
) : apiError ? <Redirect to='/error' /> : (
<Landing isLoaded={this.state.isLoaded}></Landing>
)}
</Router>
);
I'm seeing a logical error with it.
<Route exact path='/error' render={props => <Error {...props} />} />
Doesn't exist when apiError.
This probably work for you:
render() {
const { currentUser, isLoaded, apiError } = this.state;
let route = (<Landing isLoaded={isLoaded} />);
if (currentUser) {
route = (
<div className='App'>
<Switch>
<Route exact path='/title/:id' render={props => <ShowTitle {...props} /> } />
<Route exact path='/shuffle' render={props => <Titles {...props} isLoaded={isLoaded} /> } />
<Route exact path='/about' render={props => <About {...props} /> } />
<Route exact path='/all-titles' render={props => <Titles {...props} isLoaded={isLoaded} /> } />
<Route exact path='/error' render={props => <Error {...props} />} />
<Route exact path='/' render={props => <Redirect to={'/' + currentUser.viewType} /> } />
<Route exact path='/logout' component={Logout} />
<Redirect to='/all-titles' />
</Switch>
</div>
);
}
if (apiError) {
route = (
<Switch>
<Route exact path='/error' render={props => <Error {...props} />} />
</Switch>
);
}
return (
<Router>
{route}
</Router>
);
};
For better usage, I recommend to you declare all routes statically, on HOC module, then validate props and use Redirect component to navigate to other path.

Categories