I'm using create-react-app and my routes doesn't load unless I refreshed the page first.
Does that have something to do with historyFallbackApi: true inside of webpack's config?
here's the code.
const AppRouter = () => {
return (
<Router>
<Route exact path="/" component={Chatbot} />
<Route path = "/about" component = {About} />
</Router>
);
};
class App extends Component {
render() {
return (
<div className="App">
<Navbar />
<AppRouter />
</div>
);
}
}
Related
I have multiple components with different paths (routes) and would like to export those to a single Main router component.
For example:
routeComponent1.js
export default function childRoutes() {
return (
<div>
<Route path="/foo" component={foo} />
<Route path="/bar" component={bar} />
</div>
);
}
routeComponent2.js
export default function childRoutes2() {
return (
<div>
<Route path="/foo2" component={foo2} />
<Route path="/bar2" component={bar2} />
</div>
);
}
I would like to use it in
root.js
import routeComponent1 from 'routeComponent1.js';
import routeComponent2 from 'routeComponent2.js';
class Root extends Component {
constructor(props) {
super(props);
}
render() {
return <Router>{routeComponent1}</Router>;
}
}
It is giving an error - Invariant Violation: <Route> elements are for router configuration only and should not be rendered.
Expecting the
<Router>
<div>
<Route path="/foo" component={foo} />
<Route path="/bar" component={bar} />
</div>
</Router>
routeComponent1 and routeComponent2 are React components. React components are Capitalized and rendered as JSX.
Example:
import RouteComponent1 from 'routeComponent1.js';
import RouteComponent2 from 'routeComponent2.js';
class Root extends Component {
render() {
return (
<Router>
<RouteComponent1 />
<RouteComponent2 />
</Router>
);
}
}
Assuming you're using the latest version of react router (v6), you can use nested routes as described here: https://reactrouter.com/en/main/start/overview#nested-routes
So this is what your App.jsx might look like:
import {
BrowserRouter as Router, Routes, Route
} from "react-router-dom";
import {AuthRoute, NonAuthRoute, UserParent} from "../components";
import {
Dasboard, UserList, CreateUser, SignIn, Page404
} from "./pages"
// Define your paths here ...
export const paths = {
SIGN_IN: "/sign-in",
DASHBOARD: "/dashboard",
LIST_USERS: "/users/list"
CREATE_USERS: "/users/create"
}
// All your routes which require authentication (requires login)
const authRoutes = [
{
path: paths.DASHBOARD,
element: <Dashboard />
},
]
// Authenticated routes but need a particular parent component
const userAuthRoutes = [
{
path: paths.LIST_USERS,
element: <UserList />
},
{
path: paths.CREATE_USERS,
element: <CreateUser />
}
]
// Paths that dont require authentication
const nonAuthRoutes = [
{
path: paths.SIGN_IN,
element: <SignIn />
},
]
const App = () => {
return (
<Router>
<Routes>
{/* AUTHENTICATED ROUTES */}
<Route element={<AuthRoute />}>
{authRoutes.map((route, index) =>
<Route key={index} {...route} />;
)}
{/* User Management */}
<Route element={<UserParent />}>
{userAuthRoutes.map((route, index) =>
<Route key={index} {...route} />
)}
</Route>
</Route>
{/* NON-AUTH ROUTES */}
<Route element={<NonAuthRoute />}>
{nonAuthRoutes.map((route, index) =>
<Route key={index} {...route} />;
)}
</Route>
<Route path="*" element={<Page404 />} />
</Routes>
</Router>
)
}
React Breadcrumbs is throwing some error when using with Router.
I am following this tutorial for implementation.
http://learnreact.robbestad.com/breadcrumbs
Below is the code:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
{Breadcrumbs}
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
Below is the error:
Objects are not valid as a React child (found: object with keys {Breadcrumb, Breadcrumbs}). If you meant to render a collection of children, use an array instead.
You shouldn't pass the reference directly but use it with React.createElement or in other words, in JSX land you should do just <Breadcrumbs />.
If you look carefully at the code from the link you posted (http://learnreact.robbestad.com/breadcrumbs):
var Breadcrumbs = require('react-breadcrumbs');
MyComponent = React.createClass({
render: function() {
return (
<div>
<Breadcrumbs />{/* You see it here, <Breadcrumbs /> not {Breadcrumbs} */}
</div>
);
}
});
It creates new React element and now let's check your code:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
{Breadcrumbs}{/* <-------- Here is the issue */}
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
If you replace {Bredcrumbs} with <Breadcrumbs />, it should just work:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
<Breadcrumbs />
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
You can read more about JSX in the official React documentation:
https://reactjs.org/docs/introducing-jsx.html
I have used this library https://www.npmjs.com/package/react-breadcrumbs-dynamic][1] to implement the breadcrumbs.
Created one route.js and imported the library
import { Breadcrumb as BootstrapBreadcrumb } from 'react-bootstrap'
import { Breadcrumbs, BreadcrumbsItem } from 'react-breadcrumbs-dynamic';
import CrumbItem from '../components/common/breadcrumb/CrumbItem';
Created the breadcrumbs container like this in route.js:
const Routes = () => (
<BrowserRouter>
<div>
<div className="breadcrumbs-container">
<BreadcrumbsItem glyph='home' to={base_path}>
Home Page
</BreadcrumbsItem>
<Breadcrumbs
hideIfEmpty={{ active: true }}
item={CrumbItem}
container={BootstrapBreadcrumb}
finalProps={{ active: true }}
duplicateProps={{ to: 'href' }}
/>
</div>
<Route exact path='/' component={HomePage} />
<Route path='/brands' component={Brands} />
<Footer />
</div>
</BrowserRouter>
);
Given breadcrumbs items in Another component brands.js
import { BreadcrumbsItem } from 'react-breadcrumbs-dynamic';
render() {
return (
<BreadcrumbsItem to={'/brands'}>
Brands
</BreadcrumbsItem>
)
}
Created link container separately
import { Breadcrumb } from 'react-bootstrap'
import { LinkContainer } from 'react-router-bootstrap'
const CrumbItem = ({to, ...props}) => (
<LinkContainer to={to}>
<Breadcrumb.Item {...props}>
</Breadcrumb.Item>
</LinkContainer>
)
export default CrumbItem
Note: Using bootstrap is optional
I want to use layouts with my react-router-dom, at this moment i am doing that like this
const DefaultLayout = ({children, ...rest}) => {
return (
<div className={styles.wrapper}>
<Header/>
{children}
<Footer/>
</div>
)
};
const DefaultRoute = ({component: Component, ...rest}) => {
return (
<Route {...rest} render={matchProps => (
<DefaultLayout>
<Component {...matchProps} />
</DefaultLayout>
)}/>
)
};
render(
<Provider store={store}>
<HashRouter>
<Switch>
<DefaultRoute exact path="/" component={AdvertList}/>
<DefaultRoute exact path="/user" component={UserOptions}/>
<Route path="/login" children={Login}/>
<Route render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</HashRouter>
</Provider>,
document.querySelector('#app')
);
it works okay, both UserOptions and AdvertList components are rendered inside DefaultLayout, and Login component does not, but in official documentation i didn't find solution like that, instead there is "nested routing" where you adding new nested routes in subclasses, like
if you need default layout u make it on route /, then if you need advert list with that layout, in layout component you defined route /adverts and adding link to it, and so on, each sub component uses layout of parent one.
But in my case there is already product list on route /, and i need to change that content to other products list regarding link pressed, not to add to parent layout, but to change it part. Here is my code,
const { BrowserRouter, Route, Switch, Link } = window.ReactRouterDOM;
const { Component } = window.React;
const About = () => ('About');
const MiscProducts = () => ('Misc products');
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/miscProducts">Misc Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
Main Products
</div>
</main>
<footer>Footer</footer>
<Route path="/miscProducts" component={MiscProducts} />
</div>
)
};
};
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={AdvertsList} />
<Route path="/about" component={About} />
<Route path="*" render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</BrowserRouter>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
http://jsfiddle.net/gmcke2a4/6/ here main products loaded by default, and when i press misc products, misc products must be loaded instead of main one.
p.s. And why about doesn't work?
Login Fix
<Route path="/login" children={Login}/> this seems wrong because children component expects function which return nodes i think.Try <Route path="/login" children={() => (</Login />)}
Layout
But in my case there is already product list on route /, and i need to
change that content to other products list regarding link pressed, not
to add to parent layout
You can create component which renders specific products like this.
const MainProducts = () => 'Main Products'
const GummyBearsProducts = () => 'GummyBears'
const Products = props => (
<div className="products-container">
<Switch>
<Route path={`${props.location.pathname}`} component={MainProducts}/>
<Route path={`${props.location.pathname}/gummy-bears`} components={GummyBearProducts}/>
</Switch>
</div>
)
And then use it as follows.
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/products">Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
<Route path="/products" component={Products} />
</div>
</main>
<footer>Footer</footer>
</div>
)
};
};
React router is great in rendering specific components.I hope it answers your question.Cheers!
If you are using react-router-dom v6. Then follow the below procedure to configure react-router-dom,
App.jsx:
import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './Components/Home'
import About from './Components/About'
import Layout from './Components/Layout'
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
After configuring the react router in App.jsx. I am creating 3 components Home, About and Layout. Home and About are regular components and Layout component is to handle the Layout part in react-router-dom using Outlet.
Layout.jsx
import { Outlet, Link } from 'react-router-dom'
export default function Layout() {
return (
<>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Outlet />
</>
)
}
Home.jsx
export default function Home() {
return (
<>
<p>This is Home</p>
</>
)
}
About.jsx
export default function About() {
return (
<>
<p>This is About Us</p>
</>
)
}
How to skip the react routing in case of file paths? It seems react router intercepts all links. Example below - the hardcoded link /1.pdf seems to trigger the router.
How do we trigger file downloads?
const Main = () => {
return (
<div>
<h1>React Router Playground</h1>
<Link to="/download">Download Area</Link>
</div>
);
};
const Download = () => {
return (
<div>
<h1>Download Area</h1>
Download
</div>
);
};
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<Router>
<div>
<Route exact path="/" component={Main} />
<Route path="/download" component={Download} />
</div>
</Router>
);
}
}
This is a rather simple example so the hardcoded link. These are dynamic and passed as props in the actual code.
The following code combined with a NoMatch component should work, reloading the URL if it's a valid resource.
<Router>
<div>
<Switch>
<Route exact path="/" component={Main} />
<Route exact path="/download" component={Download} />
<Route component={NoMatch} />
<Route onEnter={() => window.location.reload()} />
</Switch>
</div>
</Router>
I did find out that I can't use when I'm rendering my app on the server. I would like to wrap my App in specified router depending on the situation - BrowserRouter on the CLient side and StaticRouter on server side. My App looks like this:
imports......
class App extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<BrowserRouter>
<div>
<Menu />
<main>
<Switch>
<Route exact path="/about" component = {About} />
<Route exact path="/admin" component = {BooksForm} />
<Route exact path="/cart" component = {Cart} />
<Route exact path="/" component = {BookList} />
</Switch>
<Footer />
</main>
</div>
</BrowserRouter>
);
}
componentDidMount(){
this.props.getCart();
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
getCart
}, dispatch)
}
export default connect(null, mapDispatchToProps)(App);
I tried to move my BrowserRouter ou of this component so my index.js would look like this:
imports....
const renderApp = () => (
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App/>
</BrowserRouter>
</Provider>
)
const root = document.getElementById('app')
render(renderApp(), root)
So I would get ability to wrap my app in different routers. The problem is when I moved BrowserRouter out of my App component it stopped working. Clicking on links just does not work anymore. The url is changing but my app isn't rendering differnet components. How can I move router out of this component?
On the server, you'll wrap your app similar to this:
const routerContext = {};
const appComponent = (
<Provider store={store}>
<StaticRouter location={req.url} context={routerContext}>
<App />
</StaticRouter>
</Provider>
);
Where you pass react-router the location (from the url) as well as a context object.
The client side is like your example:
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App/>
</BrowserRouter>
</Provider>