Nested routes with react router v4 not working - reactjs

I have create a route for a page.In side that page I have use 4 component.I have give path to these to these component.In header dropdown I have given links to these components, On first click the path is change.
but in second click the url is change but not redirecting.
const menu = (
<Dropmenu>
<Menu
key="menu"
style={{ backgroundColor: '#0f2037', borderRadius: '0' }}
>
<Menu.Item key="golive">
<Link to={'/s/live'} style={{ color: '#fff' }}>
<Icon type="video-camera" />
Start Live Broadcast
</Link>
</Menu.Item>
<Menu.Item key="mychannel" style={{ color: '#fff' }}>
<Link to={'/s/profile'} style={{ color: '#fff' }}>
<Icon type="user" />
Manage Profile
</Link>
</Menu.Item>
<Menu.Item key="settings">
<Link to={'/s/account'} style={{ color: '#fff' }}>
<Icon type="setting" />
Account
</Link>
</Menu.Item>
<Menu.Item
key="logout"
onClick={this.logoutCall}
style={{ color: '#fff' }}
>
<Icon type="logout" />
Logout
</Menu.Item>
</Menu>
</Dropmenu>
);
<BrowserRouter>
<Switch>
<Route path="/s" component={GoLive} />
<Route
path="/s/profile"
render={() => (
<div>
<ManageProfile descri={teprop} />
</div>
)}
/>
</Switch>
</BrowserRouter>

Adding exact to Routes will solve the problem:
<Route path="/s" exact={true} component={GoLive} />
<Route
exact={true}
path="/s/profile"
render={() => (
<div>
<ManageProfile descri={teprop} />
</div>
)}
/>
The Switch component renders the first matching route and /s is matched in /s/profile/ .

You can use exact in Route:
<Route exact path="/one" component={About}/>
https://reacttraining.com/react-router/web/api/Route/exact-bool

Related

Some images not loading on github pages after deploying. React

Hi I deployed a new react app to ghpages. One of the pages has a Tab Container with 3 Nav Items that serve as a link. The first tab which auto loads with the page shows all the images correctly. The second and third tab do not show the pages. These images are rendered properly when I run it locally. They are all coded the same way. Anyone know how to solve this?
Link to ghpages https://johntrieseverything.github.io/starcraft2-unit-counter/
The error occurs under the "Units List" section when selecting the second or third tab.
Here is what my code looks like:
<Tab.Container defaultActiveKey="Protoss" >
<Container fluid className='unitListDisplayBackground'>\
<Row style={{ height: '10vh' }}></Row>
<Row className='mt-5'>
<h1>Units List</h1>
<p>This is a page where you can view all playable units and see their stats</p>
</Row>
<Row>
<Nav fill variant='tabs' defaultActiveKey="/home">
<Nav.Item >
<Nav.Link
style={{ backgroundColor: '#393e46', color: '#ADD8E6', marginBottom: '1vh' }}
eventKey="Protoss">
<img
src={process.env.PUBLIC_URL + "/assets/Icons/Protoss Icon.png"}
alt='Protoss Icon'
style={{ width: '50px', height: '50px' }}
/></Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
style={{ backgroundColor: '#393e46', color: '#ADD8E6', marginBottom: '1vh' }}
eventKey="Zerg">
<img
src={process.env.PUBLIC_URL + "/assets/Icons/Zerg Icon.png"}
alt='Zerg Icon'
style={{ width: '65px', height: '50px' }}
/>
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
style={{ backgroundColor: '#393e46', color: '#ADD8E6', marginBottom: '1vh' }}
eventKey="Terran">
<img
src={process.env.PUBLIC_URL + "/assets/Icons/Terran Icon.png"}
alt='Terran Icon'
style={{ width: '50px', height: '50px' }}
/>
</Nav.Link>
</Nav.Item>
</Nav>
<Tab.Content>
<Tab.Pane eventKey="Protoss" style={{ textAlign: 'center' }}>
{/* Display the Protoss Units */}
<ProtossUnits />
</Tab.Pane>
<Tab.Pane eventKey="Zerg" style={{ textAlign: 'center' }}>
{/* Display the Zerg Units */}
<ZergUnits />
</Tab.Pane>
<Tab.Pane eventKey="Terran" style={{ textAlign: 'center' }}>
{/* First 3 Terran units */}
<TerranUnits />
</Tab.Pane>
</Tab.Content>
</Row>
</Container>
</Tab.Container>
Another issue I'm having is the 404 error on page refresh. I read that the Hashbrowser is a quick work around but the react router doc says its not recommended. What are some other potential solutions?
Code for routing:
class App extends Component {
render() {
return (
<div>
<BrowserRouter basename="starcraft2-unit-counter">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/UnitsList" element={<UnitsList />} />
<Route path="/UnitCountersPage" element={<UnitCountersPage />} />
<Route path="/ArmyCounterPage" element={<ArmyCounterPage />} />
</Routes>
</BrowserRouter>
</div>
)
}
}
Thank you!
Tried looking online for similar problems but couldn't find one..

NavLink react-router-dom not working ( working if refresh page )

I have try to use NavLink in react-router-dom but something not working. Thanks for any help.
I'm in Profile page, i click <NavLink to="/adminboard/settings">and it change the path to '/adminboard/settings' and activeClassName in Settings but i'm still in Profile page. Then i refresh page, it's going to the Settings page.
my code :
<AdminNav style={{ margin: '0px', padding: '0px', marginTop: '160px' }}>
<Router style={{ margin: '0px', padding: '0px' }}>
<Switch style={{ margin: '0px', padding: '0px' }}>
<Route exact path="/adminboard/profile" component={AdminboardProfile} />
<Route exact path="/adminboard/postsanpham" component={AdminPostSanPham} />
<Route exact path="/adminboard/settings" component={AdminSetting} />
<Route exact path="/adminboard/store" component={AdminStore} />
</Switch>
</Router>
</AdminNav>
my Nav code:
<NavLink to="/adminboard/profile" activeClassName="active">
<span>{faUserIcon}</span>
<span>Profile</span>
</NavLink>
<NavLink to="/adminboard/postsanpham" activeClassName="active">
<span>{postsanpham}</span>
<span>Store</span>
</NavLink>
<NavLink to="/adminboard/store" activeClassName="active">
<span>{faClipboardListIcon}</span>
<span>Store</span>
</NavLink>
<NavLink to="/adminboard/settings" activeClassName="active">
<span>{faToolboxIcon}</span>
<span>Settings</span>
</NavLink>
I guess the problem is because you did not use the exact attribute as in
<Route exact path='/category' component={Category}></Route>
exact will look for complete route ie '/adminboard/settings' if exact is not used it will stop looking further if a match is first found (it matches with 'adminboard' and will not look further)

React: How to render components based on MenuItem clicked?

Below is the code:
import React from 'react';
import { Layout, Menu, Breadcrumb } from 'antd';
import { UserOutlined, ProfileFilled, CreditCardFilled, SearchOutlined, BankOutlined} from '#ant-design/icons';
const { SubMenu } = Menu;
const { Header, Content, Sider, Footer } = Layout;
function Admin(){
function handleClick(){
console.log("Search")
}
return(
<Layout>
<Header className="header">
<div className="logo" />
<Menu theme="light" mode="horizontal" defaultSelectedKeys={['2']} icon={<UserOutlined />}>
<Menu.Item key="1">Creame Cookies</Menu.Item>
</Menu>
</Header>
<Layout>
<Sider width={200} className="site-layout-background">
<Menu
theme="dark"
mode="inline"
defaultOpenKeys={['Dashboard']}
defaultSelectedKeys={['Dashboard']}
style={{ height: '250%', borderRight: 0, width: 250 }}
>
<Menu.Item key="Dashboard" icon={<UserOutlined />}>
Dashboard
</Menu.Item>
<Menu.Item onClick={handleClick} key="Search" icon={<SearchOutlined />}>
Search
</Menu.Item>
<SubMenu key="Profiles" icon={<ProfileFilled />} title="Profiles">
<Menu.Item key="1">Free Profiles</Menu.Item>
<Menu.Item key="2">Premium Profiles</Menu.Item>
</SubMenu>
<Menu.Item key="Payments" icon={<CreditCardFilled />}>
Payments
</Menu.Item>
</Menu>
</Sider>
<Layout style={{ padding: '0 72px 72px' }}>
<Content
className="site-layout-background"
style={{
padding: 24,
margin: 0,
minHeight: 500,
}}
>
<h1>Default</h1>
</Content>
</Layout>
</Layout>
{/*<Footer style={{ textAlign: 'center' }}>Creame Cookies Ltd</Footer> */}
</Layout>
)
}
export default Admin
Now, I need to render components at the location of the h1 tag with text as Default, based on the menuitem clicked. I am unsure of how to do this in react since I am new to it and feeling it difficult as compared to vannila javascript and jQuery in which I have already worked.
<h1>{someCondition ? 'Text A': 'Text B'}</h1> is generally how you handle this. You can always do the condition at the top of the component before your return statement if you prefer.
{ } is syntax to wrap an expression in React. You could put a ternary or just a variable in there to render.
Could also do <h1>{someCondtion ? <ComponentA /> : <ComponentB />}</h1>.

React Router renders two components on the same page

I've looked at the other questions similar to this, and none of them seem to solve this.
I want to use react router to link to another page.
This is the return of my component:
<NativeRouter>
<View style={styles.container}>
<TextInput
onChangeText={value => this.onChangeText('username', value)}
style={styles.input}
placeholder='username'
/>
<TextInput
onChangeText={value => this.onChangeText('password', value)}
style={styles.input}
secureTextEntry={true}
placeholder='password'
/>
<Button style={styles.button} title="Sign In" onPress={this.signIn.bind(this)} />
<TextInput
onChangeText={value => this.onChangeText('confirmationCode', value)}
style={styles.input}
placeholder='Confirmation Code'
/>
<Button style={styles.button} title="Confirm Sign In" onPress={this.confirmSignIn.bind(this)} />
<Link to='/forgotPassword'>
<Text>Forgot Password</Text>
</Link>
<Switch>
<Route path='/forgotPassword' component={ForgotPassword} />
</Switch>
</View>
</NativeRouter>
Whenever I click on the link, the link renders the ForgotPassword component on the same page.
Ideas?
This is inside my app.js.
<Switch>
<Route path="/signin" component={SignIn} />
<Route path="/forgotPassword" component={ForgotPassword} />
</Switch>
</View>
the Route inside your component will get replaced with ForgoPassword component when the url matches, You should define the routes in the parent component
Example
import React from "react";
import { StyleSheet, Text, View, AppRegistry } from "react-native";
import { NativeRouter, Route, Link } from "react-router-native";
const Home = () => <Text style={styles.header}>Home</Text>;
const SignIn = () => <Text style={styles.header}>SignIn</Text>;
const ForgotPassword = () => <Text style={styles.header}>ForgotPassword</Text>;
const App = () => (
<NativeRouter>
<View style={styles.container}>
<View style={styles.nav}>
<Link to="/" underlayColor="#f0f4f7" style={styles.navItem}>
<Text>Home</Text>
</Link>
<Link to="/signIn" underlayColor="#f0f4f7" style={styles.navItem}>
<Text>Sign In</Text>
</Link>
<Link
to="/forgotPassword"
underlayColor="#f0f4f7"
style={styles.navItem}
>
<Text>Forgot Password</Text>
</Link>
</View>
<Route exact path="/" component={Home} />
<Route path="/signIn" component={SignIn} />
<Route path="/forgotPassword" component={ForgotPassword} />
</View>
</NativeRouter>
);
const styles = StyleSheet.create({
container: {
marginTop: 25,
padding: 10
},
header: {
fontSize: 20
},
nav: {
flexDirection: "row",
justifyContent: "space-around"
},
navItem: {
flex: 1,
alignItems: "center",
padding: 10
},
subNavItem: {
padding: 5
},
topic: {
textAlign: "center",
fontSize: 15
}
});
AppRegistry.registerComponent("MyApp", () => App);
sandbox

How to change Content based on Menu Item click in AntD (React UI Library)

I am following AntD Menu tutorial from here and it shows how to use this component. But I am failed to understand that how to change my Content when I click on different menu option. Tried searching a lot but did not find any useful help.
import { Layout, Menu, Icon } from 'antd';
const { Header, Sider, Content } = Layout;
class SiderDemo extends React.Component {
state = {
collapsed: false,
};
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
}
render() {
return (
<Layout>
<Sider
trigger={null}
collapsible
collapsed={this.state.collapsed}
>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1">
<Icon type="user" />
<span>nav 1</span>
</Menu.Item>
<Menu.Item key="2">
<Icon type="video-camera" />
<span>nav 2</span>
</Menu.Item>
<Menu.Item key="3">
<Icon type="upload" />
<span>nav 3</span>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0 }}>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
onClick={this.toggle}
/>
</Header>
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280 }}>
Some Conent
</Content>
</Layout>
</Layout>
);
}
}
ReactDOM.render(<SiderDemo />, mountNode);
Can you pls help.
Just WRAP your Layout tag inside Router tag of react-router-dom.
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Layout, Menu, Icon } from 'antd';
import Dashboard from './containers/Dashboard/Dashboard';
import Meseros from './containers/Meseros/Meseros';
const { Header, Content, Footer, Sider } = Layout;
const SubMenu = Menu.SubMenu;
class RouterApp extends Component {
state = {
collapsed: false,
};
onCollapse = (collapsed) => {
this.setState({ collapsed });
}
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
}
render() {
return (
<Router>
<Layout style={{ minHeight: '100vh' }}>
<Sider
collapsible
collapsed={this.state.collapsed}
onCollapse={this.onCollapse}>
<div className="logo" />
<Menu theme="dark" defaultSelectedKeys={['1']} mode="inline">
<Menu.Item key="1">
<Icon type="pie-chart" />
<span>Deshboard</span>
<Link to="/" />
</Menu.Item>
<Menu.Item key="2">
<Icon type="desktop" />
<span>Meseros</span>
<Link to="/meseros" />
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0, paddingLeft: 16 }}>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
style={{ cursor: 'pointer' }}
onClick={this.toggle}
/>
</Header>
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280 }}>
<Route exact path="/" component={Dashboard} />
<Route path="/meseros" component={Meseros} />
</Content>
</Layout>
</Layout>
</Router>
);
}
}
export default RouterApp;
If you don't want to change the route every time you choose a menu item you can use the following approach
function MyComponent(){
const [selectedMenuItem, setSelectedMenuItem]= useState('item1');
const componentsSwtich = (key) => {
switch (key) {
case 'item1':
return (<h1>item1</h1>);
case 'item2':
return (<h1>item2</h1>);
case 'item3':
return (<h3>item3/h3>);
default:
break;
}
};
return(
<div>
<Menu selectedKeys={selectedMenuItem} mode="horizontal" onClick={(e) =>
setSelectedMenuItem(e.key)}>
<Menu.Item key="item1">your first component here</Menu.Item>
<Menu.Item key="item2">your second here</Menu.Item>
<Menu.Item key="item3">your third here</Menu.Item>
</Menu>
<div>
{componentsSwitch(selectedMenuItem)}
</div>
</div>)
You can bind onClick with your MenuItem and re render the component upon clicking any menuItem. And you can make you content in your Constant.js or initialize it in your component state.
Add onClick method
<Menu.Item
key="1"
onClick={this.handleMenuClick}
>
<Icon type="user" />
<span>nav 1</span>
</Menu.Item>
make a handle for MenuItem click:
handleMenuClick = event => {
//you can get here event.target.value
//filter the content
//setState the content your component will re render and content will be updated.
}
In case you want to change the route, there is a working example here
https://codesandbox.io/embed/fervent-thunder-egyk1?fontsize=14&hidenavigation=1&theme=dark
Add Link component in Menu.Item and wrap with BrowserRouter from react-router-dom
<Menu.Item key="2">
CI/CD Pipelines
<Link to={`${match.url}/cicd`} />
</Menu.Item>
You can add the onClick prop for the Menu item as follow:
NB. I am using NextJs router to link the menus to their own corresponding page. In case you are using React, use Link from router-dom.
<pre>
<Menu
onClick={({ keyPath }) => router.push(`/${keyPath}`)}
mode="inline"
defaultSelectedKeys={["dashboard"]}
defaultOpenKeys={["company-info"]}
items={navs}
theme="dark"
/>

Resources