I have problem with router-dom. I am working according to youtube tutorial, I cannot resolve below error:
[landingPageLayout] is not a component. All component children of must be a or <React.Fragment>. I would be greateful for some guidance.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
App.js
import './App.css';
import { Routes, Route } from 'react-router-dom';
import landingPageLayout from './components/layouts/landingPageLayout';
import homePage from './components/pages/homePage';
const App = () => {
return (
<Routes>
<landingPageLayout>
<Route path="/">
<homePage/>
</Route>
</landingPageLayout>
</Routes>
);
}
landingPageLayout.js
import React from 'react';
import Header from '../navigation/header';
const landingPageLayout = ({...otherProps}) => {
return (
<div>
<Header/>
</div>
)
}
export default landingPageLayout;
As Nicholas said in comments, your react components should always be capitalized.
Other than that, Routes component only accepts or <React.Fragment> as children so you can't add your layout like that. What you can do is something like this:
const App = () => {
return (
<Routes>
<Route
path='/*'
element={
<LandingPageLayout>
<HomePage />
</LandingPageLayout>
}
/>
</Routes>
);
}
If you have several routes that need this layout, you should replace HomePage with another component that has all the routes. For example we can call it PrivateRoutes. Then in code above you replace <HomePage /> with <PrivateRoutes /> and then your PrivateRoutes component should look like this:
const PrivateRoutes = () => {
return (
<Routes>
<Route path="home" element={<HomePage />} />
<Route path="page1" element={<Page1 /> />
//rest of routes
</Routes>
);
}
Related
When I try using the useLoaderData hook from react-router-dom, it has been giving me the same error
Uncaught Error: useLoaderData must be used within a data router. See
https://reactrouter.com/routers/picking-a-router.
no matter what change I make in the Home Component, so that made me guess the issue is not from there.
This is what my Main.jsx looks like:
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
)
My App.jsx:
import React from 'react'
import { Route, Routes } from 'react-router-dom'
import Home, { homeLoader } from './pages/Home'
import About from './pages/About'
import GlobalLayout from './GlobalLayout'
const App = () => {
return (
<>
<Routes>
<Route path='/' element={<GlobalLayout />}>
<Route index element={<Home />} loader={homeLoader} />
<Route path='/about' element={<About />} />
</Route>
</Routes>
</>
)
}
export default App
I think everything in my Home.jsx is fine
I have tried checking out the documentation attached to the error and its not helping.
In order to use the RRDv6.4 Data APIs a data router must be used. See Picking a Router.
Use the createBrowserRouter utility to create a Data router. The created router object is passed to the RouterProvider component. Any routes and components that you want or need to use the Data APIs necessarily need to be declared here at build time as part of the data router creation.
App.jsx
import React from 'react';
import {
createBrowserRouter,
createRoutesFromElements,
RouterProvider,
Route,
Routes
} from 'react-router-dom';
import Home, { homeLoader } from './pages/Home';
import About from './pages/About';
import GlobalLayout from './GlobalLayout';
const router = createBrowserRouter(
createRoutesFromElements(
<Route element={<GlobalLayout />}>
<Route path="/" element={<Home />} loader={homeLoader} />
<Route path="/about" element={<About />} />
</Route>
)
);
const App = () => {
return <RouterProvider router={router} />;
};
export default App;
Main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
createBrowserRouter
RouterProvider
createRoutesFromElements
This question already has an answer here:
React router routers not showing
(1 answer)
Closed 4 months ago.
Intro
I had created a react starter application
Problem
I had created a 3 components in /src/pages named AddCoupon, Addvertical, Addmetadata. Now then I created a file Routes.js in /src.
Routes.js
import React from 'react';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import AddCoupon from './pages/addCoupon';
import AddMetadata from './pages/addMetadata';
import AddVertical from './pages/addVertical';
import Login from './pages/login';
const Routes = () => {
return (
<>
<Router>
<Switch>
<Route path="/addcoupon">
<AddCoupon />
</Route>
<Route path="/addmetadata">
<AddMetadata />
</Route>
<Route path='/addvertical'>
<AddVertical />
</Route>
<Route path="/">
<Login />
</Route>
</Switch>
</Router>
</>
)
}
export default Routes
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter as Router } from 'react-router-dom'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Router >
<App />
</Router>
</React.StrictMode>
);
reportWebVitals();
What I want?
So basically what I want is that when I type http:localhost:3000/addcoupon, it should render AddCoupon Component and same for other 2 components but right now it's showing nothing.
I dont want to use any navbar. What I want is simply when I hit the endpoints mentioned in Route.js, it should render that component.
Router 6 uses different syntax compared to earlier versions. Please check out the documentation:
https://reactrouter.com/en/v6.3.0/getting-started/overview
For your particular case, you need to remove switch, and pass element to route, and wrap all Route elements in Routes element, like so:
const Routes = () => {
return (
<>
<Routes>
<Route path="/addcoupon" element={<AddCoupon />}/>
<Route path="/addmetadata" element={<AddMetadata />}/>
<Route path='/addvertical' element={<AddVertical />}/>
<Route path="/" element={<Login />}/>
</Routes>
</>
)
}
In order for routes to work, you also need to wrap App element in Router element, like below:
import ReactDOM from 'react-dom'
import { BrowserRouter as Router } from 'react-router-dom'
import App from './App'
import './styles/index.scss'
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
)
Final step, render Routes inside of App element or wherever you want to use it:
const App = () => {
return <Routes/>
}
I know this question has been asked a lot and I've looked at quite a lot of answers and articles including one on how to upgrade from React Router V5 to V6 since I'm used to V5. However, V6 is giving me a weird issue which I don't know how to fix or what am I doing wrong.
Here's my code below
App.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Login from './components/dashboard/Login';
import Profile from './components/dashboard/Profile';
import './resources/style/tutorApp.css';
export default class App extends Component {
static displayName = App.name;
render () {
return (
<Router>
<Routes>
<Route path="/" element={ <Profile /> } />
<Route path="/Login" element={ <Login /> } />
</Routes>
</Router>
);
}
}
Profile.js
import React, { Component } from 'react';
class Profile extends Component {
render() {
return (
<div>
<h1>This is my Profile Page.</h1>
</div>
);
}
}
export default Profile;
Login.js
import React, { Component } from 'react';
class Login extends Component {
render() {
return (
<div>
<h1>This is my Login page.</h1>
</div>
);
}
}
export default Login;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const rootElement = document.getElementById('root');
ReactDOM.render(
<BrowserRouter basename={baseUrl}>
<App />
</BrowserRouter>,
rootElement);
registerServiceWorker();
I just get a blank window in the browser. Nothing is rendered!
What is the problem?
You are mounting a router inside another router.
In ReactDom.render you're wrapping your app in BrowserRouter.
import { BrowserRouter } from 'react-router-dom';
// ...
ReactDOM.render(
<BrowserRouter basename={baseUrl}> // <-- this is the outer browser router
<App />
</BrowserRouter>,
rootElement
);
However inside your app you mount another BrowserRouter in your render method.
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
// ...
render () {
return (
<Router> // <-- this is the nested browser router
<Routes>
<Route path="/" element={ <Profile /> } />
<Route path="/Login" element={ <Login /> } />
</Routes>
</Router>
);
}
To fix the problem simply remove one or the other.
The rest of your code looks fine.
I have this fully functional and very basic code:
import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter, Route, Switch} from "react-router-dom";
import Home from "./App/home.jsx";
import About from "./App/about.jsx";
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route exact path="/" component={Home}></Route>
<Route path="/About" component={About}></Route>
</Switch>
</BrowserRouter>,
document.getElementById("main")
);
I realise that no matter what, Home and About components is always going to be loaded, but not always used.
How can I fix this? I've tried:
import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter, Route, Switch} from "react-router-dom";
import Home from "./App/home.jsx";
import About from "./App/about.jsx";
let path = require("path");
function C(file) {
return function(obj) {
let url = path.join("./App", file);
let C = require(url);
return <C {...obj}/>
}
}
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route exact path="/" component={C("home.jsx")}></Route>
<Route exact path="/" component={C("about.jsx")}></Route>
</Switch>
</BrowserRouter>,
document.getElementById("main")
);
But then, it doesn't get rendered.
So is there any way that I can load only the components I need for the current web page.
perhaps using code splitting in this fashion
https://reactjs.org/docs/code-splitting.html
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</div>
);
}
So perhaps your code could be like this
I have this fully functional and very basic code:
import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter, Route, Switch} from "react-router-dom";
const Home= React.lazy(() => import('./App/home.jsx'));
const About= React.lazy(() => import('./App/about.jsx'));
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route exact path="/" component={Home}></Route>
<Route path="/About" component={About}></Route>
</Switch>
</BrowserRouter>,
document.getElementById("main")
);
You can use React-Loadable package for the use-case you mentioned above. Example code is shown below, follow along with it.
import Loadable from 'react-loadable';
const loading = () => (
<div>
Loading... //Custom loader
</div>
);
const AsyncLogin = Loadable({
loader: () => import('./Login/index.jsx'),
loading: loading,
});
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route path='/login' component={AsyncLogin} />
</Switch>
</BrowserRouter>,
document.getElementById("main"));
You can find the react-loadable documentation here. Or alternatively, you can configure Webpack and achieve the required results.
I have a react app. It is working fine. It uses redux,react-router 3. The routes work fine, but when I press the back button, they route gets duplicated. For example from localhost:3000/admin/main which I am currently, when I go back, it goes to localhost:3000/admin/admin/main, which return not found.
Here is my routes code:
export default (
<Route path="/" component={App}>
<Route path="home" component={requireNoAuthentication(HomeContainer)} />
<Route path="login" component={requireNoAuthentication(LoginView)} />
<Route exact path="admin/user" component={requireAuthentication(UserView)} />
<Route exact path="admin/main" component={requireAuthentication(UsersListView)} />
<Route path="secure" component={requireAuthentication(CustomerView)} />
<Route exact path="*" component={DetermineAuth(NotFound)} />
</Route>
);
I also get a console error: Adjacent JSX elements must be wrapped in an enclosing tag. If anyone can help it would be great thanks!!
Your HOC wrappers (requireNoAuthentication and requireAuthentication) and using exact (I think this might a react-router v4 only feature?) might be messing with your route history. Try restructuring your routes so that all of them fall under App -- some of the routes fall under RequireAuth, while the rest are public.
As a side note: you can avoid using React.cloneElement with passed down class methods and state by using Redux instead.
routes/index.js
import React from "react";
import { browserHistory, IndexRoute, Router, Route } from "react-router";
import App from "../components/App";
import Home from "../components/Home";
import Info from "../components/Info";
import ShowPlayerRoster from "../components/ShowPlayerRoster";
import ShowPlayerStats from "../components/ShowPlayerStats";
import Schedule from "../components/Schedule";
import Sponsors from "../components/Sponsors";
import RequireAuth from "../components/RequireAuth";
export default () => (
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route component={RequireAuth}>
<IndexRoute component={Home} />
<Route path="roster" component={ShowPlayerRoster} />
<Route path="roster/:id" component={ShowPlayerStats} />
<Route path="schedule" component={Schedule} />
</Route>
<Route path="info" component={Info} />
<Route path="sponsors" component={Sponsors} />
</Route>
</Router>
);
index.js
import React from "react";
import { render } from "react-dom";
import App from "../routes";
import "uikit/dist/css/uikit.min.css";
render(<App />, document.getElementById("root"));
components/App.js
import React, { Component, Fragment } from "react";
import { browserHistory } from "react-router";
import Header from "./Header";
export default class App extends Component {
state = {
isAuthenticated: false
};
isAuthed = () => this.setState({ isAuthenticated: true });
unAuth = () =>
this.setState({ isAuthenticated: false }, () => browserHistory.push("/"));
render = () => (
<Fragment>
<Header
isAuthenticated={this.state.isAuthenticated}
unAuth={this.unAuth}
/>
{React.cloneElement(this.props.children, {
isAuthenticated: this.state.isAuthenticated,
isAuthed: this.isAuthed
})}
</Fragment>
);
}
components/RequireAuth.js
import React, { Fragment } from "react";
import Login from "./Login";
export default ({ children, isAuthenticated, isAuthed }) =>
!isAuthenticated ? (
<Login isAuthed={isAuthed} />
) : (
<Fragment>{children}</Fragment>
);