How to redirect page using Route? - react-router

I kinda wanna do a function that when i click on every item in the navbar and even the submenu in each item, it will rediret me to a new page with relevant information, i thought of using Route inside my Link tag but i kinda stuck in how to do that. Should i use Route or other codes to achive this task? I'd like to hear recommendations from you guys, thank you btw!
Navbar.js:
import React, { useState } from "react";
import { navItems } from "./NavItems";
import { Link, BrowserRouter as Router } from "react-router-dom";
import "./Navbar.css";
import DropDown from "./DropDown";
function Navbar() {
const [dropDown, setDropdown] = useState(false);
return (
<div>
<ul className="nav-items">
{navItems.map((item) => {
if (item.title === "Services") {
return (
<li
onClick={() => setDropdown(!dropDown)}
key={item.id}
className={item.cName}
onMouseEnter={() => setDropdown(true)}
onMouseLeave={() => setDropdown(false)}
>
<Router>
<Link to={item.path}>{item.title}</Link>
</Router>
{dropDown && <DropDown />}
</li>
);
}
return (
<Router>
<li key={item.id} className={item.cName}>
<Link to={item.path}>{item.title}</Link>
</li>
</Router>
);
})}
</ul>
</div>
);
}
export default Navbar;
DropDown.js:
import React from "react";
import { serviceDropdown } from "./NavItems";
import { Link, BrowserRouter as Router } from "react-router-dom";
import "./DropDown.css";
function DropDown() {
return (
<div>
<ul className="subnav-items">
{serviceDropdown.map((item) => {
return (
<Router>
<li key={item.id} className={item.cName}>
<Link to={item.path}>{item.title}</Link>
</li>
</Router>
);
})}
</ul>
</div>
);
}
export default DropDown;
Sandbox link: https://codesandbox.io/s/dropdown-menu-ho4h8?file=/src/components/DropDown.js:0-560

One possible solution would be to use the useHistory hook from react-router and use the push method to move to a different page. The code would look as follows
const history = useHistory();
// Use the onClick props of your dropdown element
onClick={() => history.push("other URL");}

Related

Wrapping h5 in Link tag made h5 dissappear

I am trying to make a component go to localhost:3000/second. The header for the component(AddNote) displays when I dont wrap it in a Link tag, but when I do, the whole page becomes blank, including the "My Notes" which is supposed to be displayed by default.
import React, {useState} from 'react';
import './App.css';
import {BrowserRouter as Router, Routes, Route, Switch} from 'react-router-dom';
import AddNote from './components/noteDisplay/addNote/newNote.js'
import FirstPage from './components/noteDisplay/firstPage.js'
import NoteDisplay from './components/noteDisplay/noteDisplay.js'
import secondPage from './components/secondPage/secondContainer.js'
const App = () => {
return (
<div className="App">
<h1 className="app-title">My notes</h1>
<Router>
<div>
<Routes>
<Route path='/second' element={<secondPage />}/>
{/*<Route path='/' element={<NoteDisplay/>}/>*/}
</Routes>
</div>
</Router>
<AddNote/>
</div>
);
}
import React from 'react';
import { Route, BrowserRouter as Router, Link, Switch } from 'react-router-dom';
import NoteDisplay from '../noteDisplay';
import { v4 as uuidv4 } from 'uuid';
const AddNote = () => {
console.log('hi')
return (
<div>
<Link to="/second">
<h5 className="add-note">New note</h5>
</Link>
</div>
)
}
export default AddNote;
You need to change your <Link /> code to be something like below.
const AddNote = () => {
return (
<div>
<h5>
<Link href="/second">New Note</Link>
</h5>
</div>
);
};
See the official Next.js documentation for how to use it - it explains it in greater detail!

React won't render my components using router

I am very new to react and trying to work on my first website.
I have tried to seek my problem online, I've encountered similar questions to mine but could not figure out my exact problem.
My layout of components are in a scroll down style (portfolio), when I try route for example to my contact component it wont render unless I refresh my page. also instead of scrolling down to component it will pop up at the top .(Hope I am clear)
My App Function
import { useState } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';
import Contact from './Components/Contact/Contact';
import Form from './Components/FormArea/Form/form';
import Introdoction from './Components/Introdoction/Introdoction';
import NavBar from './Components/NavBar/NavBar';
import NavigationBar from './Components/NavigationBarHeader/NavigationBar/NavigationBar';
import Portfolio from './Components/Portfolio/Portfolio';
import Routing from './Components/Routing/Routing';
import Skills from './Components/Skills/Skills';
function App() {
return (
<BrowserRouter>
<Switch>
<div className="App">
<NavigationBar/>
<section className="section">
<Route path="/contact" component={Contact} exact/>
<Introdoction/>
<Portfolio/>
<Skills/>
{/* <Contact/> */}
<Form/>
</section>
</div>
</Switch>
</BrowserRouter>
);
}
export default App;
I am trying to configure "Contact" component for this example.
My Menu/Navbar Component
import { Component, MouseEventHandler } from "react";
import {MenuItems} from "../MenuItems/MenuItems";
import "./NavigationBar.css";
import icon from '../../../Assets/icon.png'
import {Button} from "../Button/Button";
import { NavLink, Redirect, Route, Switch, useHistory } from "react-router-dom";
import Contact from "../../Contact/Contact";
class NavigationBar extends Component {
state = {clicked : false}
handleClick = () => {
this.setState ( { clicked: !this.state.clicked } );
};
public render(): JSX.Element {
return (
<nav className="NavbarItems ">
<img className="navbar-logo"src={icon } />
<div className="menu-icon" onClick={this.handleClick}>
<i className={this.state.clicked ? 'fas fa-times' : 'fas times'}></i>
</div>
<ul className={this.state.clicked ? 'nav-menu active' : 'nav-menu'}>
{MenuItems.map((item,index) => {
return (
<li key={index}>
<NavLink to={item.url} className={item.cName} >{item.title} </NavLink>
</li>
)
})}
</ul>
<Button>Sign up</Button>
</nav>
);
}
}
export default NavigationBar;
ItemMenu Component
import { NavLink } from "react-router-dom";
import "./MenuItems.css";
export const MenuItems = [
{
title: 'Home',
url: '/Home',
cName: 'nav-links'
},
{
title: 'Introduction',
url: '/introduction',
cName: 'nav-links'
},
{
title: 'Skills',
url: '/skills',
cName: 'nav-links'
},
{
title: 'Projects',
url: '/projects',
cName: 'nav-links'
},
{
title: 'Contact',
url: '/contact',
cName: 'nav-links'
},
];
I could add more information if needed. I hope my question is clear on what my problem is.
Thanks.
If I understood your question correctly, you want one single page, with everything below each other, and when you press a link, it scrolls you down to that place. In that case I would use:
<Contact id="contact" />
react-router creates new sub pages, which you don't want (if I understood you correctly)

Unexpected re-rendering of components

I'm trying to navigate back to a Menu component, but when I trigger a route to do so, the previous rendered Practice component is rendered in the root domain level, which should just be for the Menu component.
The solutions for similar questions on StackOverflow say to use exact in the route, but as you can see I have this in place.
How do I make this work as expected? Thanks.
Here's what I have...
App.js
import React from 'react';
import './App.css';
import PracticeContextProvider from './contexts/PracticeContext';
import {BrowserRouter as Router, Route, Switch, Link} from 'react-router-dom';
import Menu from './pages/Menu';
function App() {
return (
<div className="app">
<PracticeContextProvider>
<Menu />
</PracticeContextProvider>
</div>
);
}
export default App;
Menu.js
import React, { useContext } from 'react';
import {BrowserRouter as Router, Route, Switch, Link, useParams, useLocation, useRouteMatch} from 'react-router-dom';
import { PracticeContext } from '../contexts/PracticeContext';
import Practice from './Practice';
import ModuleLanguageSelector from '../components/ModuleLanguageSelector';
import ModuleListMenuItem from '../components/ModuleListMenuItem';
const Menu = () => {
const { modulesJson } = useContext(PracticeContext);
return (
<div>
<h1>Menu</h1>
<Router>
<Switch>
<Route exact path="/">
<ModuleLanguageSelector />
{ modulesJson && (
modulesJson.map(module => {
return (
<Link to={'/Practice/' + module._id} key={ module._id }>
<ModuleListMenuItem module={ module }></ModuleListMenuItem>
</Link>
)
})
)}
</Route>
<Route exact path="/Practice/:moduleId" component={Practice} />
</Switch>
</Router>
</div>
);
}
export default Menu;
Practice.js
import React, { useContext } from 'react';
import {BrowserRouter as Router, Route, Switch, Link, useParams, useLocation, useRouteMatch} from 'react-router-dom';
import { PracticeContext } from '../contexts/PracticeContext';
import Menu from './Menu';
import ModulePracticeAnswerArea from '../components/ModulePracticeAnswerArea';
import ModulePracticeQuestion from '../components/ModulePracticeQuestion';
import ModulePracticeProgress from '../components/ModulePracticeProgress';
import ModulePracticeTutorial from '../components/ModulePracticeTutorial';
const Practice = () => {
const { moduleId } = useParams();
const { questionIndex } = useContext(PracticeContext);
return (
<Router>
<div className="module-practice-screen">
<h1>Practice</h1>
<div className="module-practice-container">
<Link to={'/'}>
<button className="quit-practice">X</button>
</Link>
{
moduleId ?
<React.Fragment>
{/*<ModulePracticeTutorial moduleId={ moduleId } />*/}
<ModulePracticeProgress questionNumber={ questionIndex } />
<ModulePracticeQuestion moduleId={ moduleId } questionNumber={ questionIndex } />
<ModulePracticeAnswerArea moduleId={ moduleId } questionNumber={ questionIndex } />
</React.Fragment>
:
<h3>The menu should appear here!</h3>
}
</div>
</div>
<Switch>
<Route exact path="/" component={Menu} />
</Switch>
</Router>
);
};
export default Practice;
You don't need <Router> and <Switch> in Practice
const Practice = props => {
const { moduleId } = useParams();
const { questionIndex } = useContext(PracticeContext);
return (
<div>
<div className="module-practice-screen">
<h1>Practice</h1>
<div className="module-practice-container">
<Link to="/">
<button>X</button>
</Link>
{moduleId ? (
<React.Fragment>
{/*<ModulePracticeTutorial moduleId={ moduleId } />*/}
<ModulePracticeProgress questionNumber={questionIndex} />
<ModulePracticeQuestion
moduleId={moduleId}
questionNumber={questionIndex}
/>
<ModulePracticeAnswerArea
moduleId={moduleId}
questionNumber={questionIndex}
/>
</React.Fragment>
) : (
<h3>The menu should appear here!</h3>
)}
</div>
</div>
</div>
);
};
codesandbox

How to pass my item from JSON to another page or class/component in ReactJS

I want to pass my data from one page to another but in an specific way.
I have a json brought via AJAX with this method (resp, error and result):
myArrayItems
import React, { Component } from 'react';
import logo from '../images/logo.png';
import '../App.css';
import { Container, Row, Col } from 'react-bootstrap';
import { Route, IndexRoute } from 'react-router';
import { BrowserRouter as Router, Switch, Link } from 'react-router-dom';
class myArrayItems extends Component {
componentDidMount() {
fetch("https://myrestserver/myArrayItems")
.then(response => response.json())
.then(
(result) => {
console.log(result)
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
And in my View i rendered like that with key.
<ul>
{items.map(item => (
<li key={item.title} className="list-group-item border-0">
<div className="wrapper">
<div className="myclass">
<Link to={{ pathname: "/myitem/" }} className="App-link">
<p className="text-left">{item.title}</p>
</Link>
</div>
</div>
</li>
))}
</ul>
}
export default myArrayItems;
So I want to pass the item.id, item.title, item.x to the page myitem, but i imported the myArrayItems and still get undefined.
What I want to achieve is in my first class to display a list of items (What i did) but when i click on any of these items, to access them in the page myitem.
myitem.js
import React, { Component } from 'react';
import logo from '../images/logo.png';
import '../App.css';
import { Container, Row, Col } from 'react-bootstrap';
import { Route, IndexRoute } from 'react-router';
import myArrayItems from './myArrayItems';
const Background = {
background: '#004272'
}
class myitem extends Component {
render(){
return (
<div className="App">
<header style={Background} className="text-center py-2 m-0">
<img src={logo} className="img-fluid w-75"/>
</header>
<Container>
<ul>
<p>{item.title}</p>
</ul>
</Container>
</div>
);
}
}
export default myitem;
I hope you can help me with that, thanks!
UPDATE:
I'm creating a WebApp using ReactJS Library with "npx create-react-app".

appbar responsive with options with react router v4, material-ui and apollo client

I'm working with apollo client, react, reac routerv4 and material-ui, my app is working ,
before insert material-ui i had
<Link to="/" className="navbar">React + GraphQL Tutorial</Link>
then i've inserted material-ui
<AppBar
title="Title"
iconClassNameRight="muidocs-icon-navigation-expand-more"
/>
but it's not clear for me how to add links for the title and options, in responsive mode with small screen the options i think must be invisible, in small screen not.
The official material-ui site is not well explained by example like bootstrap, so i need a litlle of help.
the full code is:
import React, { Component } from 'react';
import {
BrowserRouter,
Link,
Route,
Switch,
} from 'react-router-dom';
import './App.css';
import ChannelsListWithData from './components/ChannelsListWithData';
import NotFound from './components/NotFound';
import ChannelDetails from './components/ChannelDetails';
import AppBar from 'material-ui/AppBar';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import {
ApolloClient,
ApolloProvider,
createNetworkInterface,
toIdValue,
} from 'react-apollo';
const networkInterface = createNetworkInterface({ uri: 'http://localhost:4000/graphql' });
networkInterface.use([{
applyMiddleware(req, next) {
setTimeout(next, 500);
},
}]);
function dataIdFromObject (result) {
if (result.__typename) {
if (result.id !== undefined) {
return `${result.__typename}:${result.id}`;
}
}
return null;
}
// customResolvers:
// This custom resolver tells Apollo Client to check its cache for a Channel object with ID $channelId
// whenever we make a channel query. If it finds a channel with that ID in the cache,
// it will not make a request to the server.
const client = new ApolloClient({
networkInterface,
customResolvers: {
Query: {
channel: (_, args) => {
return toIdValue(dataIdFromObject({ __typename: 'Channel', id: args['id'] }))
},
},
},
dataIdFromObject,
});
class App extends Component {
render() {
return (
<ApolloProvider client={client}>
<BrowserRouter>
<MuiThemeProvider muiTheme={getMuiTheme()}>
<div className="App">
<Link to="/" className="navbar">React + GraphQL Tutorial</Link>
<AppBar
title="Title"
iconClassNameRight="muidocs-icon-navigation-expand-more"
/>
<Switch>
<Route exact path="/" component={ChannelsListWithData}/>
<Route path="/channel/:channelId" component={ChannelDetails}/>
<Route component={ NotFound }/>
</Switch>
</div>
</MuiThemeProvider>
</BrowserRouter>
</ApolloProvider>
);
}
}
export default App;
the right is add a code like this:
<AppBar position="static">
<Toolbar>
<IconButton color="contrast" aria-label="Menu">
</IconButton>
<Typography type="title" color="inherit" >
{"Admin"}
</Typography>
<AuthLink to="/customers" label="Customers"/>
<AuthLink to="/tours" label="Tours"/>
<AuthLink to="/signout" label="Sign Out"/>
<AuthLink to="/signin" label=" Sign In" whenLogged="false"/>
</Toolbar>
</AppBar>
Authlink is just a component that I wrote to show the options and where simple I add the Title to display options.
const AuthLink = (props) => {
let auth = checkAuth();
return (
( (auth && !props.whenLogged ) || (!auth && props.whenLogged == "false") ) ? (
<Link to={props.to} className="navbar"><Button>{props.label}</Button></Link>
) : (
null
)
);
}
"Button" is a component from material, "Link" from react-router, here the imports:
import {
BrowserRouter,
Link,
Route,
Switch,
Redirect,
} from 'react-router-dom';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import IconButton from 'material-ui/IconButton';