In my render function I have
<Route path="/classes/:course" render={(match) => (
<Redirect to={`/classes/${match.params.course}/home`} />
)}>
<Route path="/home" component={Home} />
</Route>
For example if the param for "course" was "BIO1001", I want to redirect the page to "/classes/BIO1001/home" when I go to the page "/classes/BIO1001/". Previously I tried simply putting a Redirect tag with "from" and "to" but ran into the problem of the url actually going to "/classes/:course/home" instead of "/classes/BIO1001/home"
Also would the nested route with path="/home" go to "/classes/BIO1001/home"? I was unsure on how I can set a route where the path starts from the previous url (in this case starting from "/classes/:course/"
The first problem is right here:
render={(match) => ( ...
The render function gets a props object which contains a match property. Instead of destructuring the match property, what you are actually doing is assigning the whole props object to a variable match. So when you go to access match.params it won't be found.
You need curly braces around match in order to destructure it.
render={({match}) => ( ...
The second problem is the nesting of the two Route components. I get a warning:
Warning: You should not use <Route render> and <Route children> in the same route; <Route render> will be ignored
So based on that warning you can see that your Redirect is being entirely ignored since it comes from render. The child Route is seen as the render function for the classes Route.
I'm assuming you have various subpages of a course? And we want to force the URL to include "/home" if none is set? (Personally I would do the opposite and redirect "/home" to the course root URL).
Previously I tried simply putting a Redirect tag with "from" and "to" but ran into the problem of the url actually going to "/classes/:course/home" instead of "/classes/BIO1001/home"
Per the docs, you can use params in your Redirect, but only if it is inside a Switch.
Here's a sample code to do that:
const CoursePage = () => {
// you can access arguments from the props or through hooks
const { course, tab } = useParams();
// not sure how you want to handle the different tabs
return <div>Viewing Course {course}</div>;
};
const App = () => (
<BrowserRouter>
<Switch>
<Route path="/classes/:course/:tab"><CoursePage/></Route>
<Redirect from="/classes/:course" to="/classes/:course/home"/>
</Switch>
</BrowserRouter>
);
export default App;
Your nested routing is true i think. But you are rendering your Home component without any dynamic props. Try it like below:
<Route path="/classes/:course" render={(match) => (
<Redirect to={`/classes/${match.params.course}/home`} />
)}>
<Route path="/home" >
<Home someProps={someValue} />
</Route>
</Route>
Note: The Redirect element can be used without a containing Route element by providing a from property. In this case, you can just use the URL parameter tokens in both from and to, and they'll be carried over for you. For example, if you're using a Switch block...
<Switch>
{/* various app routes... */}
{/* redirect action */}
<Redirect from="/classes/:course" to="/classes/:course/home" />
<Switch>
Related
I am using a HashRouter to render different pages. The problem I am having is that when I visit
/service/app/sort, it renders <MainPage /> when I am expecting it to render <ChildPage />.
Here's similar to what my router looks like
<HashRouter>
<Switch>
<Route path="/service/app">
<MainPage />
</Route>
<Route path="/service/app/sort">
<ChildPage />
</Route>
</Switch>
</HashRouter>
Additional information that may help:
on my <MainPage />, I have a button to redirect onClick
const history = useHistory();
const handleSortClick = () => {
console.log('click me')
let path = "/service/app/sort";
history.push(path);
};
When I click it once, I get the 'click me' console.log and the link changes to /service/app/sort, but it's still the <MainPage />. If I click it one more time, I get the warning
"Warning: Hash history cannot PUSH the same path; a new entry will not be added to the history stack"
You're probably facing this problem because the start of the URL is being interpreted as truthy by react-router-dom, and is letting you access the /service/app anyway.
For example, the /service/app route will not only detect this route, but will also detect /service/app/1 or /service/app1 just because it has /service/app in the path.
To prevent this, you need to pass the exact property to the route, so react-router will understand that you need to access exactly this route to render that component.
<Route path="/service/app" exact={true}>
<MainPage />
</Route>
So I'm trying to display a 404 page if the path in my web app is undefined or nothing is rendered due to something having been deleted. For example, users can create books and the books id becomes the path to that page. But if a user deletes that book, the path will be undefined. So, if that happens id like to be able to make sure that any other user that tries to go onto that page is shown a 404 message.
For example, a link could be
'/home/undefined'
or
'/undefined/books'
To create any sort of "404 route", you simply have to add a route that matches any URL, and use it in a switch tag along with the valid routes. For instance:
<Switch>
<Route path ="/home" component={Home} />
<Route path ="/home/book" component={Book} />
<Route path ="/" component={FourZeroFour} />
</Switch>
You can also achieve the same effect by not using a Switch, and instead using exact on every route except the final one:
<Route path ="/home" component={Home} exact />
<Route path ="/home/book" component={Book} exact />
<Route path ="/" component={FourZeroFour} />
But what if you have a route that potentially matches both invalid and valid URLS, for instance:
<Route path ="/home/book/:bookId" component={SpecificBook} />
(where :bookId could be undefined)
In that case, you'll instead want to check the URL parameter's validity inside your component. For instance, your SpecificBook component might do the following:
const SpecificBook = ({ bookId } ) => {
if (bookId === 'undefined') return <Redirect to="/404" />;
// rest of component
}
You could also use history.push, but the Redirect tag will do more than just add a history entry; it will simulate a (server-side) redirect.
I will check the book_id first and the redirect if not found.
import {useHistory} from "react-router-dom"
function App() {
const history = useHistory();
if (!bookId) {
history.push("/404");
return null;
}
return <></>
}
From below code ,if i remove routes variable from code1 and go with code2 code than
i did not face any problem .but if i comment code2 routes variable and work with the code1
than i am facing problem that when i click on submit button of Auth.js file or /auth route
(without or with selecting any ingredient from /burgerBuilder route.
when user click on submit button of Auth.js file .it will dispatch auth action in redux store
than that will dispatch authStart than after receiving response from firebase than we dispatch authSuccess which changes token and some other data in redux.
than this changes will rerender all component who has auth object state in their mapStateToProps.but token is not updating in mapStateToProps in Auth.js file
where am i wrong .
complete code you can check on below link
[1]: https://codesandbox.io/s/goofy-kowalevski-mos8f?fontsize=14&hidenavigation=1&theme=dark
but i am getting problem when i conditioned routes in App.js file. if i dont do that than it works fine more i have already described in App.js file with code as well.
class App extends Component {
render(){
//console.log("App.js");
//code1::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
let routes ;
routes = (
<Switch>
<Route path="/auth" component={Auth}/>
<Route path="/" exact component={BurgerBuilder} />
</Switch>);
if(this.props.token)
{
routes = (
<Switch>
<Route path="/checkout" component={Checkout} />
<Route path="/orders" component={Orders} />
<Route path="/logout" component={Logout} />
<Route path="/" exact component={BurgerBuilder} />
</Switch>);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//code2:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
routes = (
<Switch>
<Route path="/auth" component={Auth}/>
<Route path="/checkout" component={Checkout} />
<Route path="/orders" component={Orders} />
<Route path="/logout" component={Logout} />
<Route path="/" exact component={BurgerBuilder} />
</Switch>);
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
return (
<div>
<Layout>
{routes}
</Layout>
</div>
);
}
componentDidMount() {
this.props.onAuthCheck();
}
}
const mapStateToProps = (state)=>{
return {
token:state.auth.token
}
}
const mapDispatchToProps = (dispatch) => {
return{
onAuthCheck:() =>dispatch(authCheckState()) //when try to auto signin
}
}
export default withRouter(connect(mapStateToProps,mapDispatchToProps)(App));
what i have already tried -> i have followed a question on stackoverflow that was telling that is because of unupdated react and react-dom .i am stuck in it from 12 hours .
thanks in advance.
i already mentioned that when i got the problem in question .when user was submitting the form it causes rerendering because of i received token from a server using an auth action.and i have conditioned my routes in such a way that it does not contain auth.js file (login/signup) page route. so that now it(auth.js) does not render because i omitted route of auth.js file(login/signup page).and even i have logged in and successfully received token but was still on the same url because the redirection code that i have written inside auth.js file does not execute.
some more information and refrence more clarity .-->
i known Link or NavLink component is related to Route .
but how it actually related
but actually what happening is .link component is internally an anchor tag when you click on that it changes your url .if your url changes mean it is changing your url property of match property of prop object.and in react we know if any prop changes it causes re-rendring.when it re-render the corresponding route whose path matches with the url render the component in its component props.
//////////////////////////////////////////////////////////////////////////////////////////
from react-router documentation .
Route Matchers-->
There are two route matching components: Switch and Route. When a is rendered,{*** it searches through its children elements to find one whose path matches the current URL. When it finds one, it renders that and ignores all others***}. This means that you should put s with more specific (typically longer) paths before less-specific ones.
If no matches, the renders nothing (null).
//////////////////////////////////////////////////////////////////////////////////////////
I am developing a React js blog-like web site and I am finding some trouble managing the routes. My pages with articles' URLs are like this: website/pages/3
I would like to redirect to homepage when the page index is 1, since the homepage is the first page with articles by default.
My Router looks like this:
<Router>
<Switch>
<Route exact path="/" render={() => <Page postsPerPage={3}/>} />
<Route exact path="/Page/:activePage" render={() => <Page postsPerPage={3}/>} />
<Route path="/Login" component={Login} />
<PrivateRoute path="/AddPost" component={AddPost} />
<Route path="/:postLocation" component={Post} />
</Switch>
</Router>
I would like to route "/Page/:activePage" to the component the route "/" renders if the activePage is 1. So the component would be the same (Page), but the path would be different.
Could conditional rendering in the Router do the trick, and if so, how? I was thinking about something along these lines:
<Route exact path="/Page/:activePage" render={() =>
{
let {activePage} = useParams()
if (activePage == 1) return (<Redirect to="/"/>)
else return(<Page postsPerPage={3}/>)
}
}/>
However it seems React is not happy about me using useParams there (there's a compilation error: React Hook "useParams" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks)
I tested that snippet with a constant value of 1 instead of the activePage parameter and it does redirect so that basically leaves me with the question of how do I retrieve the parameter from the path?
Render function in this case The render prop function has access to all the same route props (match, location and history) as the component render prop.
so you can basically do something like.
<Route exact path="/Page/:activePage" render={(props) =>
{
if (props.match.params.activePage == 1) return (<Redirect to="/"/>)
else return(<Page postsPerPage={3}/>)
}
}
/>
Looking at your example case above, I will rather not redirect anything but carry the logic into the Page component. inside the componentDidMount or useEffect function that extracts the activePage param. I will check if it's 1(or whatever sentinal value you choose to use) Then I perform the logic that will have been performed by the home component else I proceed normally with the route. eg If you extracted it and do a fetch to the backend for the case where its, not 1, then when it's 1 you could just return from the function and it will work as if it were on the home page. alternatively, after the check, if it's 1 you could then redirect back to '/'.
You should probably handle the routing within your Pages component or if you prefer, create a separate component to handle the conditional routing.
for example:
function Pages (props) {
const {activePage} = useParams()
return activePage === 1 ? <Redirect to='/' /> : (
<div>
Your Pages component content here
</div>
)
}
export default Pages;
or
function ConditionalRoutingComponent(props) {
const {activePage} = useParams()
return activePage === 1 ? <Redirect to='/' /> : <Page postsPerPage={3}/>
}
export default ConditionalRoutingComponent;
Hope this helps
The render function of Component the is called with three parameters namely match, history and location. You can use them to perform the action you are trying to do with hooks.
<Route ... render={({match}) => {
if (match.params.activePage == 1) {
doYourStuff()
}
}}
This is my routing configuration, when i access the index route which is "/"
it works perfectly fine, but when i access the /posts and /response route, it cant resolve it.
See that is my index route. and this happens when i go to posts or response route
Ok, first of all, it seems like you're using an unnecessary Router component, you can check here why: https://reacttraining.com/react-router/web/api/Router
Also, you can wrap your routes inside a Switch component, but you will have to change the order of them since a Switch only renders the first route that matches the path given. You can read more about that here https://reacttraining.com/react-router/web/api/Switch. So your routes definition will become something like this:
<Switch>
<Route path="/r1" render={() => <h1>route 1</h1>} />
<Route path="/r2" render={() => <h1>route 2</h1>} />
<Route exact path="/" component={SomeComponent} />
</Switch>
try wrapping your all 3 Route inside a Switch statement