I have my application looking something like below..
import FirstComponent from "./components/firstComponent";
import NextComponent from "./components/nextComponent";
import MyProgressComponent from "./components/progressComponent";
class App extends React.Component {
render() {
return (
<Router>
<div>
<MyProgressComponent />
<Route path="/" exact component={FirstComponent} />
<Route path="/nextComponent" component={NextComponent} />
</div>
</Router>
);
}
}
As we can see 'MyProgressComponent' is visible when we navigate between 'http://localhost:3000/' and 'http://localhost:3000/nextComponent' because it is directly nested under Router component in App component. But I want 'MyProgressComponent' to be visible only in 'http://localhost:3000/nextComponent' and hidden in 'http://localhost:3000/'. Any suggestion ?
I can do this by importing 'MyProgressComponent' inside each component wherever required but I don't want to duplicate it in each component.
You can render multiple components using the below syntax
<Route path="/nextComponent" render={() =>
<>
<MyProgressComponent />
<NextComponent />
</>
}
/>
Based on #Crocsx comment you can apply following check on your code.
<Router>
<div>
{this.props.location.pathname === "/nextComponent" ? <MyProgressComponent />: null}
<Route path="/" exact component={FirstComponent} />
<Route path="/nextComponent" component={NextComponent} />
</div>
</Router>
you can use switch provided by router to achieve this.
Something like below should work for you.
<Switch>
<Route exact path="/nextComponent" component={MyProgressComponent} />
</Switch>
<Switch>
<Route path="/" exact component={FirstComponent} />
<Route path="/nextComponent" component={NextComponent} />
</Switch>
more documentation is available here https://reacttraining.com/react-router/web/guides/basic-components
Related
I am learning about React (Coming from ASP.NET). When I go to '/employee' it will display employee list table. But when I go to '/employee/create' it will display both the table and the create form. How to display only create employee form when I to '/employee/create' ?
export default class App extends Component {
static displayName = App.name;
render() {
return (
<Layout>
<Route exact path='/' component={Home} />
<Route path='/counter' component={Counter} />
<AuthorizeRoute path='/fetch-data' component={FetchData} />
<Route exact path='/employee' component={EmployeeIndex} />
<Route path='/employee/create' component={EmployeeCreate} />
<Route path='/employee/details/:id' component={EmployeeDetails} />
</Layout>
);
}
}
To do that, you will need to add a <Switch> around your Routes:
import { Route, Switch } from "react-router";
<Switch>
<Route exact path='/' component={Home} />
<Route path='/counter' component={Counter} />
<AuthorizeRoute path='/fetch-data' component={FetchData} />
<Route exact path='/employee' component={EmployeeIndex} />
<Route path='/employee/create' component={EmployeeCreate} />
<Route path='/employee/details/:id' component={EmployeeDetails} />
</Switch>
It works just like a normal `switch-case, will only render the first matching path within your Routes.
Without <Switch> it will render ALL matching routes.
Here what I use in my apps.
Make separate components for all pages and import in App.js under src. Make use of state and props to store the data and create ID. Install npm i react-router-dom to access react route.
import { Switch, Route, Redirect } from "react-router-dom";
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/employee" component={Employee} />
<Route exact path="/createEmployee" component={Create} />
<Route exact path="/employeeDetails" component={Details} />
<Redirect to = "/" />
</Switch>
for homepage - Home.js
for employee list table - Employee.js
create employee - Create.js
go to employee's detail - Details.js
Redirect to - will redirect to homepage if exact URL is not entered.
i am developing an web app and I am new to react router. Evrything was going great until I found myself in need to render a whole new page, with new navbar and all.
that's my app.js
class App extends Component {
render() {
return (
<BrowserRouter>
<div className='App'>
<Layout>
<Header />
<NavigationB />
<Search />
<Switch> {/* to swtich to the desired path. Nest all route here */}
<Route path='/' component={Home} exact />
<Route path='/login' component={Login} />
<Route path='/register-choice' component={RegisterButton} />
<Route path='/register-patient' component={RegisterPatient} />
<Route path='/register-professional' component={RegisterProf} />
<Route path='/profesional-dashboard' component={ProfessionalDashboard} />
</Switch>
</Layout>
<Footer />
</div>
</BrowserRouter>
);
}
}
So, I wanted to go to /professional-dashboard but without rendenring all the components above such and Header, Search, etc.
I tried to go to my index.js file and set it up like this
ReactDOM.render(
<BrowserRouter>
<Switch> {/* to swtich to the desired path. Nest all route here */}
<Route path='/' component={App} exact />
<Route path='/professional-dashboard' component=
{ProfessionalDashboard} />
</Switch>
</BrowserRouter>,
document.getElementById('root'));
The idea was, in my form whenever I press register, it should send me to the dashboard of the professional.
At the end of my Register.js file you would find
const WrappedRegistrationForm = Form.create()(RegisterProf);
ReactDOM.render(
<BrowserRouter>
<div>
<WrappedRegistrationForm />
</div>
</BrowserRouter>
, document.getElementById('root'));
export default WrappedRegistrationForm;
I am using Ant Design, so the form renders WrappedRegistrationForm. At first it was not working then I wrapped it around BrowserRouter, I don't get the error anymore, but now when I press the register button, it takes me to /professional-dashboard but it loads app.js and not ProfessionalDashboard.js
Funny thing is, if I refresh the page, it loads ProfessionalDashboard.js normally.
Hope I'm explaining myself well.
Glad if you can help me!!
Hi could try something like this rendering the top one first if its a match if not it will go on to render the rest of the app :) hope this is clear
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route exact path='/profesional-dashboard' component={ProfessionalDashboard} />
<StandarRoute path='/' component={MainPage} />
<Switch />
</BrowserRouter>
);
}
}
class MainPage extends Component {
render(){
return(
<div className='App'>
<Layout>
<Header />
<NavigationB />
<Search />
<Switch> {
<Route path='/' component={Home} exact />
<Route path='/login' component={Login} />
<Route path='/register-choice' component={RegisterButton} />
<Route path='/register-patient' component={RegisterPatient} />
<Route path='/register-professional' component={RegisterProf} />
</Switch>
</Layout>
<Footer />
</div>
)
}
}
Try including "exact" before component in your Route, or including "exact" before the 'To' in your Link
Try,
<Route exact path="/register" render={() => ( <Redirect to="/dashboard"/>)
Why do you render two times with reactDOM by the way? That might be what’s causing the issue too. Just exporting it and putting it in route component should suffice.
For example I have these components
first.js
<div>
<Route path='/' />
<Route path='/first' />
</div>
second.js
<div>
<Route path='/second' />
<Redirect to='/something' />
</div>
And then i have a component that has this
<Switch>
<First>
<Second>
</Switch>
I am using React-Router and Switch does not work if it's child components are not Route. So how does one just strip those divs from first and second components so only things left are the routes?
You can wrap them in fragment like this:
<React.Fragment>
<Route path='/' />
<Route path='/first' />
</React.Fragment>
You can return them in an array:
return [
<Route path='/' key='root' />,
<Route path='/first' key='first' />
]
Note: returning an array is necessary to provide a key props.
I'm new to react and trying to get this whole routing thing down. I have page which I want to render multiple routes withing.
My main index.js file looks like this:
ReactDOM.render(
<BrowserRouter>
<div>
<Switch>
<Route path="/adminDash" exact component={AdminDashMain}/>
<Route path="/admin/ClientSearch" exact component={ClientDetailsMain}/>
<Route path="/" exact component={LogIn}/>
</Switch>
</div>
</BrowserRouter>
, document.getElementById('root'));
in client search main I have 3 components
class ClientDetailMain extends React.Component {
render() {
return(
<div>
<Header />
<SubHeader username={this.props.match.params.username} />
<Display username={this.props.match.params.username}/>
</div>
);
}
}
export default withRouter(ClientDetailMain);
I'm using <Display/> as a container and inside of that I want to have other route so that a person can go to
/admin/ClientSearch/refined
/admin/ClientSearch/general
/admin/ClientSearch/fixed
I figured out that the /admin/ClientSearch will match regardless so the header and subheader show on all 3 routes, however my routes which are written as:
const Display = () =>{
return(
<div>
<Route path ='/admin/ClientSearch/refined' component={<Refined/>
<Route path ='/admin/ClientSearch/general' component={<General/>
<Route path ='/admin/ClientSearch/fixed' component={<Fixed/>
</div>
)
};
export default withRouter(ClientDisplay);
aren't displaying anything. Is this how I should be writing it? When I link to and of those 3 the header and subheader show up but the components in the individuals routes don't.
For example
'/admin/ClientSearch/fixed' shows the header and subheader but none of its own components.
They key is in the "exact" attribute of your Routes. In addition, when you create a component that has routes inside, you can get the url of the previous routes through it's props. Like this example:
class Main extends React.Component {
render(){
return (
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/about' component={About} />
<Route exact path='/contact' component={Contact} />
<Route path='/admin' component={AdminArea} />
</Switch>
)
}
}
Then you have your sub-routes like this:
const AdminArea = ({match}) => (
<Switch>
<Route exact path={`${match.url}/specie`} component={Component} />
<Route exact path={`${match.url}/color`} component={Component} />
<Route exact path={`${match.url}/user/:id`} component={Component}/>
</Switch>
)
I'm used to application layouts with multiple yield areas, i.e. for content area and for top bar title. I'd like to achieve something similar in React Router. For example:
<Router>
<Route path="/" component = { AppLayout }>
<Route path="list"
component = { ListView }
topBarComponent = { ListTopBar }/>
</Route>
</Router>
AppLayout:
<div className="appLayout box">
<div className="appLayout topBar">
{ -- display ListTopBar here -- }
</div>
<div className="appLayout content">
{ -- display ListView here -- }
</div>
</div>
Both child components should receive the same props.
How can I approach this?
To passe multiple component you can do like this :
<Route path="groups" components={{main: Groups, sidebar: GroupsSidebar}} />
<Route path="users" components={{main: Users, sidebar: UsersSidebar}}>
See the doc here :
https://github.com/ReactTraining/react-router/blob/v3/docs/API.md#named-components
In v4, according to the docs, you can render multiple components like this:
<Route path='/some-path' render={() =>
<Fragment>
<FirstChild />
<SecondChild />
</Fragment>
} />
Instead of using div's you can use Fragments.
`
<Route path='/some-path' render={props =>
<Fragment>
<Child 1/>
<Child 2/>
</Fragment>
} />
`
You can also use Array in latest versions of React-router-dom;
<Route path="groups" element={[<Component1/>,<Component2/>]} />
Will work just fine.
To render multiple components you can do this:
<Route
path="/EditEmployee/:id"
render={(props) =>
<div>
<NavMenu />
<EditEmployee {...props} />
</div>
}
/>
Here I'm passing parameter to specific conponent.
//this is the simplest method to render multiple components and it works for me
<Router>
<Route path="/">
<ListView />
<ListTopBar />
</Route>
</Router>
<Route path='/' element={<><Header /> <Home /></>} />
This worked for me in the latest react router dom v6
Another method is within the render method of route multiple passed components can be created using react.createElement
<Route render ={(props)=>React.createElement(Component1, {...props}},
React.createElement(Component2, {...props}}/>
What worked for me was to wrap the multiple components in a <Fragment> or a <div> as a parent element.
return (
< Router>
<div className="App" >
<Routes>
<Route path='/'
element={
<Fragment>
< NavBar />
< NewsLetterCard />
< TestimonialsCard />
< ServicesCard />
< ContactsCard />
< Footer />
</Fragment>
}
/>
</Routes>
</div>
</Router>
);
}
For v6, where you are using Routes instead of Switch to render your components. This works:
<Router>
<Routes>
<Route path='/' element={<><Child1/> <Child2/></>} />
</Routes>
</Router>
But for v5, this works:
<Router>
<Switch>
<Route path="/">
<Child1/>
<Child2/>
</Route>
This seem to work for me, I needed to add canvas animation component as background under homepage ("/") only:
import Page from 'pages/Page';
import Blog from 'pages/Blog';
import Post from 'pages/Post';
import Category from 'pages/Category';
import CanvasParticles from 'components/canvas/CanvasParticles';
...
<Routes>
{['/', '/:slug'].map((path, index) => {
return path === '/' ? (
<Route
exact
path={path}
element={[<CanvasParticles />, <Page />]}
key={index}
/>
):(
<Route path={path} element={<Page />} key={index} />
);
})}
<Route exact path="/blog" element={<Blog />}></Route>
<Route path="/blog/:slug" element={<Post />}></Route>
<Route path="/category/:slug" element={<Category />}></Route>
</Routes>
click on this you can view a image v6 feature : this is the simplest method to render multiple components and it works for me
Main Concept is to you should wrap with element
<Route path="/" element={<> </>}
or
wrap with in Fragment
<Route path="/" element={ }