<Route path="*">
<Redirect to="/" />
</Route>
The code above is what I am using to handle all not found routes. I have all routes in switch and for the most part this is working fine <Switch>. I was wondering how I would go about sending a windows alert saying something along the lines of "this page doesn't exist" when the unknown route is called. I tried using render and calling a function, but that didn't seem to work. Any thoughts?
edit: to make it clear, I am using React framework, javascript, react-router.
Your current implementation simply redirects back to (/) when the route is not found.
However, to display a window.alert() you should consider making a new NotFound component and handle the display of the alert on that page.
Afterward, use the useHistory hook to redirect back to '/'
See example code below
NotFound Component
import { useEffect } from "react";
import { useHistory } from "react-router-dom";
const NotFound = () => {
let history = useHistory();
useEffect(() => {
window.alert('Page Not found');
history.push('/');
}, []);
return (
<div>404</div>
)
}
export default NotFound;
Existing Routes
<Route path="*">
<NotFound />
</Route>
I am using HOC(Layout component here) to wrap my custom component. The Layout component contains Header and sidebar. On clicking link, it will be rendering the respective component. But my problem is that with every route, my HOC gets rendered as route target component is wrapped in this HOC. How can I make my HOC render only once.
Example Snippet.
App.js
<Router>
<Switch>
<PrivateRoute path="routeOne" component={RouteOne}/>
<PrivateRoute path="routeTwo" component={RouteTwo}/>
</Switch>
</Router>
RouteOne.js
import React from "react"
import Layout from "/hoc"
const RouteOne = () =>{
return({..jsx..})
}
export default Layout(RouteOne)
Layout.js
const Layout(WrappedComponent) => {
const userDetails = useSelector(state);
useEffect(()=>{
dispatch(fetchSomething())
},[dispatch])
return ( <HeaderNavbarUILayout header={<Header
username={userDetails.userName}>
content={<WrappedComponent/>);
}
export default Layout
I want to render my HOC component only once. How can I do that?
EDIT:
I would follow this pattern https://simonsmith.io/reusing-layouts-in-react-router-4
const DefaultLayout = ({component: Component, ...rest}) => {
return (
<Route {...rest} render={matchProps => (
<div className="DefaultLayout">
<div className="Header">Header</div>
<Component {...matchProps} />
<div className="Footer">Footer</div>
</div>
)} />
)
};
then where you would normally define routes, replace it with this:
<DefaultLayout path="/" component={SomeComponent} />
I would take a look at the following docs:
how to use useEffect
https://reactjs.org/docs/hooks-reference.html#useeffect
how to implement should component update
https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-shouldcomponentupdate
conditionally firing an effect
```
useEffect(
() => {
...
};
},
[whatever you're watching],
);
```
The hoc being wrapped around is rendered every time and that is expected. But the React's diffing algorithm will render only the changed DOM elements. The problem here was the dispatch is being called every time when the Layout page is rendered and the state gets updated and the particular DOM hence gets updated. This gives an impression of "reload" effect. Dispatching the action conditionally will do the trick. Dispatch only when the state changes.
I'm quite new to reactjs and was just wondering if there is any easy way to display information from the same component to different routes. In the following code as an example I have just two functions that are just returning divs full of text, and calling them and rendering them right away (in the class or in the router) would just have them be on the same "page".
I've tried passing the ref by props but they always ended up undefined. I figured a state change would be awkward since there is no real "event". I'm using create-react-app, react-routerv4, and react-bootstrap.
In App.js
import React, { Component } from 'react';
import './App.css';
import NavBar from './Components/NavBar/NavBar.js';
import Band from './Components/Text/Band.js';
import { Router, BrowserRouter, Link, Route } from 'react-router-dom';
class App extends Component {
render() {
return(
<div>
<BrowserRouter>
<div className="RenderRouter">
<Route exact path='/' component={NavBar}/>
<Route exact path='/' component={ControlledCarousel}/>
<Route exact path='/' component={Home}/>
//<Route exact path='/Artists/ArtistX' component={Band}/>
<Route exact path='/Artists/Artist1' component={NavBar}/>
<Route exact path='/Artists/Artist1' render={props => <Band band1text = {this.props.band1text} />}/>
<Route exact path='/Artists/Artist2' component={NavBar}/>
<Route exact path='/Artists/Artist2' render={props => <Band band2text = {this.props.band2text} />}/>
</div>
</BrowserRouter>
</div>
);
}
}
export default App;
In Band.js
import React, { Component } from 'react';
import './Band.css';
class Band extends Component {
//Constructor for state change would go here
band1text(props) {
return(
<div id="band1Text" className="BandText">
<h1>"The best riffs!</h1>
</div>
);
};
band2text(props) {
return(
<div id="band2Text" className="BandText">
<p>More info coming soon! Check out the interview!</p>
</div>
);
};
//Create handlers to call functions, and pass reference?
render() {
return(
<div className="BandDescription">
//calling in DOM render object, can't pass props from here?
//{this.props.band1text()} = compiler error
{this.band1text()}
{this.band2text()}
</div>
);
}
}
export default Band;
It would probably be easier to just have separate components and classes for every piece of each route (i.e, BandX.js, CarouselX.js) but that could get verbose and one would have to import many files. I'm using react to build a music player component for the app as well, that's why I'm not just using standard JS.
Try writing something like this in your Band component render:
render() {
return(
<div className="BandDescription">
{this.props.band1text && this.band1text()}
{this.props.band2text && this.band2text()}
</div>
);
}
This way it checks for the prop before running whichever method. If both methods are passed, both functions will return. And you shouldn't need to pass props to those methods. Try writing them as arrow functions so they will be bound band1text = () => { ... }, you will still be able to access this.props.band1text from inside the method.
The props would be undefined because there is no props with bandText being passed down to App component. Routes are nested in App component and this.props.band1Text means you are expecting to read from props passed to App. Try passing band1Text and band2Text as props to App component.
Also to read a props that's not a function just use {this.props.band1Text} in the Band.js component
I can see in this file (https://github.com/ReactTraining/react-router/blob/v0.13.3/modules/createRouter.js) that there is a refresh function but I have no idea how to call it. I'm fairly new to react-router, I've only used it to move between some pages a couple times using hashHistory.
Right now I am trying to use it so that when an install fails, the user is given the option to 'retry' which I plan to execute by refreshing the page where the install happens (the page the user would be currently on). Any help would be appreciated.
This is a node app that runs on electron, not a web app.
firstly, add react-router as a dependency
yarn add react-router or npm install react-router
Then (for react-router v5)
import { useHistory } from 'react-router'
const history = useHistory()
// then add this to the function that is called for re-rendering
history.go(0)
This causes your page to re-render automatically
For react-router v6 use the useNavigate hook instead:
import { useNavigate } from 'react-router'
const navigate = useNavigate()
// refresh
navigate(0)
If you're using react-router v6
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const refreshPage = () => {
navigate(0);
}
You can use this to refresh Current route:
import createHistory from 'history/createBrowserHistory'
const history = createHistory();
history.go(0)
You don't really need react-router for this. You can just use location.reload:
location.reload();
Also that version of react-router you linked to is very old, I think it's linking to v1 when it's currently on v4.
I guess that you're using react-router.
I'll copy my answer from another post.
So you have few possibilities to do that, currently my favorite way to do that is using anonymous function in component prop:
<Switch>
<Route exact path="/" component={()=><HomeContainer/>} />
<Route exact path="/file/:itemPath/:refHash" component={()=><File/>} />
<Route exact path="/:folderName" component ={()=><Folder/>}/>
</Switch>
Or if you want to refresh with current url params, you'll need extra route (reload), and play a little with router stack:
reload = ()=>{
const current = props.location.pathname;
this.props.history.replace(`/reload`);
setTimeout(() => {
this.props.history.replace(current);
});
}
<Switch>
<Route path="/reload" component={null} key="reload" />
<Route exact path="/" component={HomeContainer} />
<Route exact path="/file/:itemPath/:refHash" component={File} />
<Route exact path="/:folderName" component ={Folder}/>
</Switch>
<div onClick={this.reload}>Reload</div>
React
window.location.reload();
working
if you want to re-fetch the data just do the below:
import { useLocation } from 'react-router'
const location = useLocation()
useEffect(() => {
fetchData()
}, [location.key])
I know that this is old, but I found a simple solution according to the documentation of react-router.
Just put that attribute on your Router, and whenever you are on a new Path it will force the page to reload itself.
<Router forceRefresh={true}>
Source:
https://reactrouter.com/web/api/BrowserRouter/forcerefresh-bool
This solution won't cause the undesired full page reload but requires you to make this modification to each page that needs refreshing:
export const Page = () => {
const location = useLocation();
return <PageImpl key={location.key} />
}
So the idea is: create a wrapper around your page and make React re-create the actual page every time the location key changes.
Now it's enough to call history.push(/this-page-route) again and the page refreshes.
If you want to use <Link/> to reload some route, or simply have single history push, you can setup <Redirect/> route under <Switch/> like this:
<Switch>
<Route exact path="/some-route" component={SomeRoute} />
<Redirect exact from="/some-route/reload" to="/some-route" />
</Switch>
And then <Link to="/some-route/reload" /> or push("/some-route/reload")
If you don't want to reload all scripts again you can replace the current path with a fake/empty path and replace it again with the current path like this
// ...
let currentPath = window.location.pathname;
history.replace('/your-empty-route');
setTimeout(() => {
history.replace(currentPath)
}, 0)
// ...
Update:
If the changing of the address bar bothering, you can add a patterned route like this:
<Route path="/*/reload" component={null}/>
and add /replace to the end of currentPath to replace the router with null component. like this:
// ...
let currentPath = window.location.pathname;
history.replace(`${currentPath}/replace`);
setTimeout(() => {
history.replace(currentPath)
}, 0)
// ...
In this way, the reload keyword will add to the end of your current path and I think it's more user friendly.
Notice: If you already have a route that ends with replace It will cause conflict. To solve that you should change the path of the patterned route to something else.
You could try this workaround:
// I just wanted to reload a /messages page
history.pushState(null, '/');
history.pushState(null, '/messages');
You can use this function.
function reloadPage(){
window.location.reload();
}
<input type="button" onClick={ reloadPage } value="reload"/>
May be you are trying to push in history object, then bind your component with withrouter or use window.location.href = url to redirect ..
With React Router 6 you can simply write :
import {useNavigate} from "react-router-dom";
const navigate = useNavigate()
const goToPageOnClick = () =>{
navigate(target_url)
navigate(0)
}
You can achieve that with React Router v6.
import React from 'react';
import { useNavigation, useLocation } from 'react-router-dom';
const Component = () => {
const history = useNavigation();
const location = useLocation();
const reload = () => {
navigate(location.pathname);
};
return (
...
);
};
and then put your reload function inside a useEffect hook.
PS: but this is a weird question, since react-router reloads the page automatically.
If you are needing an asynchronous reload, use history.go(0) (it wraps the History.go() method).
If you need to reload the page synchronously, use history.push(location.pathname) (it wraps the History.pushState() method).
Since there are already examples here using history.go(0), here's an example using history.push(location.pathname):
import React from 'react';
import { useHistory, useLocation } from 'react-router-dom';
const Component = () => {
const history = useHistory();
const location = useLocation();
const reload = () => {
history.push(location.pathname);
};
return (
...
);
};
update webpacker.yml
devServer: {
historyApiFallback: true,
}
Well, the easiest way is to first identify a route for reload and thereafter call the window.location.reload() function on the route like so:
<Switch>
<Route exact exact path="/" component={SomeComponent} />
<Route path="/reload" render= {(props)=>window.location.reload()} />
</Switch>
I recently had the same problem and created this(https://github.com/skt-t1-byungi/react-router-refreshable).
<Refreshable>
<Switch>
<Route path="/home">
<HomePage />
</Route>
<Route path="/post">
<PostPage />
</Route>
{/* ... */}
</Switch>
</Refreshable>
I have the following basic starting point to load a component via import().
function getComponentAsync(importPath: string) {
return async (nextState, callback) => {
const { default: Component } = await import(importPath);
callback(null, Component);
}
}
export default (
<Route path="/" component={App}>
<IndexRoute getComponent={getComponentAsync('app/components/Home')} />
</Route>
);
The goal is to simply load a component at some path. However, I keep running into some errors:
I placed a debug statement to confirm that the import path was correctly passed down to the function. It appears to be.
However, I really can't find what it is trying to import nor why it is failing to import it... why would this be? I've also tried swapping out import for require.ensure and got the same results.