React Router - trigger file download - javascript

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>

Related

React - can a component be styled depending on what other component is rendered?

I have a Search component, when the homepage component is rendered I'd like the Search component to be rendered at the bottom of the page. When any other page component is rendered I'd like the Search component to be at the top of the page.
Currently what I have my app.js as:
const App = () => {
return (
<BrowserRouter>
<Switch>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/work' component={Work} />
<Route path='/contact' component={Contact} />
</Switch>
</BrowserRouter>
)
}
and inside a page component:
const Contact = () => {
return (
<div>
<Search />
Contact
</div>
)
}
Obviously this way means I have to add the Search component to every component and choose whether I place it at the top or bottom.
My question is this, can I place it on the app.js like so:
const App = () => {
return (
<BrowserRouter>
<Search />
<Switch>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/work' component={Work} />
<Route path='/contact' component={Contact} />
</Switch>
</BrowserRouter>
)
}
And then depending on which page component is being rendered, style the Search component so it either appears at the top or bottom of the page.
Thanks
I would add a className prop to the Search component and add some if statement.
For example:
<Search className={location === '/' ? 'top' : 'bottom'} />
With the useLocation() hook provided by React Router, you can determine what page you're on.
const Contact () => {
const location = useLocation();
const styles = location === "something" ? {...topStyles} : {...downStyles};
return (
<div>
<Search style={styles} />
Contact
</div>
)
}

Why is a refresh needed to load new route with react-router

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

react-breadcrumbs throwing error when using with 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

React HashRouter not rendering other paths, only Rendering root component '/'

My Setup:
routes.js
const Router = () => (
<Switch>
<Route path="/" component={ Dashboard } />
<Route path="/somepath" component={ SomePath } />
</Switch>
);
index.js
<HashRouter>
<App />
</HashRouter>
app.js:
lass App extends Component {
render() {
return (
<div className="main-app">
<Header />
<div className="page__container">
<Router />
</div>
<Footer />
</div>
);
}
}
Issue is, when I navigate to localhost/#/ rootpath, it is correctly rendering Dashboard component as mentioned in routes.js file. But When I naviagte to localhost/#/somepath, it not rendering component for somepath, it is stil rendering / Component.
Even in React Devtool it shows <Route path="/"> is loaded, not <Route path="/somepath">
You may have to add exact to match the path. add exact prop to Route
<Route exact path="/somepath" component={ SomePath } />

React router dom and layouts

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

Categories

Resources