I am designing a multi-tabbed or multi-paged javascript web application that allows the URL to change depending on which tab you selected.
The best example I have seen is done by Zendesk
By calling it multi-tabbed, am I describing it correctly?
The tabs can be closed or opened depending on what is clicked.
How to create something like this using ReactJS? If there is a good tutorial, I am also happy to read through it.
This can easily be done with react router. If you are not familiar with react router go to the react router github page and check out the tutorials and docs. Here's an example of what it may look like to get you going.
Routes
<Route path="/" component={Application}>
<IndexRoute component={Home}/>
<Route path="tabs" component={TabLayout}>
<Route path="1" component={Tab1} />
<Route path="2" component={Tab2} />
</Route>
<Route path="about" component={About}/>
<Route path="*" component={NotFound} isNotFound/>
</Route>
Tab Layout
/* This is the layout for your tabs. Using react router to link to different tabs.
When the route changes props.children will be updated to reflect the current
route. You can add active classes to your tabs. Reference the react-router docs to
see how to do that
*/
import {Link} from 'react-router';
const TabLayout = props => {
return (
<section className="tab-container">
<div className="tabs">
<Link to="/tabs/1">Tab 1</Link>
<Link to="/tabs/2">Tab 2</Link>
</div>
<div className="content">
{props.children}
</div>
</section>
);
};
Tab 1 and tab 2 look like this
// Tab1 and Tab2 are just react components. For simplicity I am just using
// a stateless component.
const Tab1 = props => {
return (
<h1>Tab 1</h1>
);
};
Related
So here is a snippet of code from my App.js,
return (
<div className="app">
<Router>
{!user ? (
<LoginScreen />
) : (
<Switch>
<Route path='./profile'>
<ProfileScreen />
</Route>
<Route exact path="/">
<HomeScreen />
</Route>
</Switch>
)}
</Router>
</div>
Now when I click on the profile button, it takes me to a blank profile page and there are no errors, and everything compiles. Here is the ProfileScreen page code,
import React from 'react'
import './ProfileScreen.css'
function ProfileScreen() {
return (
<div className='profileScreen'>
<h1>
this is the profile screen
</h1>
</div>
)
}
console.log("hello")
export default ProfileScreen
Now the issue here is that every time I refresh the page the console.log("hello") (a test) shows up in developer tools! It also shows up in the main page before I am taken to the profile page. Also in the css file, I can change the entire background color using
* {
background-color:black;
}
So something is clearly working as I can change the background of the profile page but whenever I target the profileScreen class nothing shows up and my h1 never shows up even without styling when there should be text showing up. I am very new to reactJS and react-router-dom so I would appreciate any help! thank you.
I'm certain your profile path is incorrect. AFAIK react-router-dom v5 doesn't use relative path routing, it uses absolute path routing, so "./profile" is an invalid path. Update it to be "/profile".
<Switch>
<Route path="/profile">
<ProfileScreen />
</Route>
<Route exact path="/">
<HomeScreen />
</Route>
</Switch>
I am trying to use router in my app
so I used react-router-dom, but I am facing issues,
researched and found this link but still not helping me.
Invariant failed: You should not use <Route> outside a <Router>
can you tell me how to use route and link
i need to redirect to another page.
providing my code snippet and sandbox below.
https://codesandbox.io/s/still-smoke-uf731
let Channel = ({ channelName, channelString, onClick, active }) => (
<div onClick={onClick} className=" col-lg-2 col-md-4 col-sm-6 ">
<div>router</div>
<Router>
<Link to={"/here"}> here</Link>
<Switch>
<Route path="/auth" />
<Route path="/" />
</Switch>
</Router>
<div
className="channel-button"
style={{
backgroundColor: active === channelString ? "orange" : ""
}}
>
<p>{channelName}</p>
</div>
</div>
);
Use exact as an attribute in your home route like the following code.
<Router>
<Link to={"/here"}> here</Link>
<Switch>
<Route exact path="/" />
<Route path="/auth" />
</Switch>
</Router>
I checked your sandbox. Looks like a good start, but you messed some things up.
Here is my fork of your sandbox: https://codesandbox.io/embed/staging-fast-rr5k9
First, don't put react components in the containers, put them in the components folder and import them.
What was going on was, that you had brand new <Router> for every page you had. So I pulled the Router out. Its also not imported correctly. It should be
import { BrowserRouter as Router } from "react-router-dom";
So you pretty much need something like this
<div>
<Link to={"/bbc-news"}>BBC</Link>
</div>
<div>
<Link to={"/cnbc"}>CNBC</Link>
</div>
<Switch>
<Route
key={"fbbc-news"}
path="/bbc-news"
render={p => <Channel channelName="BBC" channelString="bbc-news" />}
/>
<Route
key={"cnbc"}
path="/cnbc"
render={p => <Channel channelName="CNBC" channelString="cnbc" />}
/>
</Switch>
</Router>
Where Channel component renders whats inside the channel. the key in Route is important, because it makes React properly trigger componentDidMount, which calls the thunk action which fetches (that one is perfect).
Then to access the results from fetch, which you have placed in Redux =>
const mapStateToProps = state => ({ json: state.json });
You don't need a lot of the things you had, so I have removed them, like the onClick, which was trying to do react routers job
You can try this:
import Stats from './containers/stats';
<Route
exact={true}
path="/"
component={Stats}
key="Mykey"
/>
I am creating an application using ReactJS. I am using react router v4 from react-router-dom.
I have written routes in index.js file.
<BrowserRouter>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path='/dashboard' component={Viewport} />
</Switch>
</BrowserRouter>
Rest of the application in Viewport.js file.
return (
<div className="">
<Sidebar navigation={this.viewport} />
<HeaderBanner user={this.props.user} />
<div className="center-panel">
//todo
//Can I use router here?
</div>
</div>
)
After user login's, I am rendering Viewport which contains Sidebar and header bar by default. Based on the item click in the sidebar navigation, I need to render components dynamically. As of now, if I write anything in the place of todo, it renders only that component for the complete browser window.
Is there any way to use routers in multiple places of the application? If yes, how can I implement it? If no, what's the best solution?
As far as I have seen, routers will be stacked at one place in the application.
Thanks in advance.
I followed a tutorial on youtube recently which was very useful
So I took some of it and applied it to your setup
<BrowserRouter>
<div>
<Route exact path="/" component={Login} />
<Route exact path='/dashboard' component={Viewport} />
</div>
</BrowserRouter>
import { NavLink, Route } from 'react-router-dom';
class Viewport extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div className="Side-bar">
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-1`}>Sub Page 1</NavLink>
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-2`}>Sub Page 2</NavLink>
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-3`}>Sub Page 3</NavLink>
</div>
<HeaderBanner user={this.props.user} />
<div className="center-panel">
<Route path={`${this.props.match.url}/sub-page-name-1`} component={SubPagePanel1} />
<Route path={`${this.props.match.url}/sub-page-name-2`} component={SubPagePanel2} />
<Route path={`${this.props.match.url}/sub-page-name-3`} component={SubPagePanel3} />
</div>
</div>
)
}
}
I removed Switch as well because I didn't use it for my sub pages... :-S
Update: Have created a repo showing a working example of sub page content
https://github.com/PocketNinjaDesign/so-sub-routes-answer
Yes you can use <Routes> in as many places as you want. <Router> components are the ones you can only use once.
I have run into an issue where React Router's NavLink is not working upon the initial render of a dashboard screen, after a successful login. After trying many different things I am posting here. You probably won't know why either but its worth a shot.
An example layout of the dashboard is as follows:
<div>
<nav>
<NavLink>Link 1</NavLink>
<NavLink>Link 2</NavLink>
<NavLink>Link 3</NavLink>
<NavLink>Link 4</NavLink>
</nav>
<div>
<!-- CONTENT -->
</div>
</div>
Upon initial render Link 2 will be unresponsive, while Link 1, 3, and 4 work fine. Clicking Link 3 for example will render new elements in the content section and then Link 2 will work.
I have tried even changing the NavLinks to anchor tags and adding my own click handler, but no matter what I try the second Link will not work until some mysterious event takes place.
Any ideas?
Edit* Add routes for #arracso
Authenticated Route:
<Switch>
<Route path="/route-1" component={SomeComponent} />
<Route path="/*" component={Dashboard} />
</Switch>
Dashboard:
<Row>
{navigationElement}
<Column>
<Switch>
<Route path="/1" component={A} />
<Route exact path="/2" component={B} />
<Route path="/2/1" component={C} />
<Route path="/2/1" component={D} />
</Switch>
</Column>
</Row>
I want to link to a specific section section of a page with react router a lot like how anchor tags would work in html. However, I couldn't find solutions with React Router version 1.0.0.
Currently, i have my router like this:
let history = createHashHistory({
queryKey: false
});
<Router history={history}>
<Route path="/" component={a}/>
<Route path="/b" component={b}/>
<Route path="/c" component={c}/>
<Route path="/d" component={d}/>
<Route path="/e" component={e}/>
<Route path="/f" component={f}/>
<Route path="/g" component={g}/>
</Router>
and I am trying to link to a specific section in the components like
<Link to="/b#{div_id}"> Go to section with div_id is component {b} </Link>
There is currently an open issue on GitHub for this. It doesn't appear to be supported, but it should be supported when using HistoryLocation when this issue is fixed.
EDIT
This is no longer supported.