I've tried all possible versions but goBack() button does not work.
Not sure what I am doing wrong but I was following this solution:
react-router (v4) how to go back?
Anyway here is the code I am trying and I have feeling that there is something to do with HashRouter.
Also How can I put the button in Navbar instead of calling it in App?
import React from 'react';
import { HashRouter, Route, withRouter } from 'react-router-dom';
import Home from "./components/Home";
import Navbar from "./components/Navbar";
import store from './store'
import PrivateRoute from './components/auth/PrivateRoute'
class App extends React.Component {
constructor(props){
super(props);
this.goBack = this.goBack.bind(this); // i think you are missing this
}
componentDidMount(){
store.dispatch(loadUser())
}
goBack(){
this.props.history.goBack();
}
render(){
return (
<Provider store={store}>
<HashRouter basename="/">
<Navbar />
<button onClick={this.goBack()}>Go Back</button>
<Route exact path="/" component={Home}/>
<PrivateRoute path="/aeons" component={AeonsList} />
</HashRouter>
</Provider>
I had an example. Please check it, hope it helps you.
import React from "react";
import {BrowserRouter as Router, Switch, Route, Link} from "react-router-dom";
import {withRouter} from "react-router";
export default function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/about/insideabout">Inside About</Link>
</li>
</ul>
<hr/>
<Switch>
<Route exact path="/">
<Home/>
</Route>
<Route exact path="/about">
<About/>
</Route>
<Route path="/about/insideabout">
<InsideAbout/>
</Route>
</Switch>
</div>
</Router>
);
}
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
const About = withRouter(({history, ...props}) => (
<div>
<h1>
About
<hr/>
<button onClick={() => {
// history.push('/')
history.goBack(-1);
}}>go back
</button>
</h1>
</div>
));
const InsideAbout = withRouter(({history, ...props}) => (
<h1 {...props}>
Inside About
<hr/>
<button onClick={() => {
history.goBack();
}}>go back
</button>
<button onClick={() => {
history.go(-2);
}}>go home
</button>
</h1>
));
This how I solved it: Create another component with Go Back button and call it anywhere you want
import React from 'react';
import { withRouter } from 'react-router';
const GoBackButton = withRouter(({history, ...props}) => (
<div>
<button onClick={() => {
// history.push('/')
history.goBack(-1);
}}>go back
</button>
</div>
));
export default GoBackButton
Related
I'm new to react and I'm trying to build application to make reservation for fishing charters for a school project I'm working on. I'm using react-router-dom which works for the most part, but when I try and use a button to navigate to page it does not render components on 2 of the pages. The page will refresh but it does not render the components "CharterDetails" or "BookCharter".
I get no errors but I do get a warning that says:
No routes matched location "/charterdetails/62fb097cb985e11cb3884f6e"
It does not seem to matter if I use the button handler or just a link both options give the same result for both CharterDetails and BookCharter, navigation for other pages render as expected.
Click here for my GitHub repository
select the work-in-progress branch
hope I’m explaining clear enough. Thank for your time
App.js:
import React, { useState, useEffect } from "react";
import Nav from "./Components/Nav";
import {
BrowserRouter as Router,
Route,
Routes,
useParams,
} from "react-router-dom";
import Login from "./Components/Users/LoginForm";
import "./App.css";
import Landings from "./Pages/Landings.js";
import Boats from "./Pages/Boats";
import Charters from "./Pages/Charters";
import CharterDetails from "./Pages/CharterDetails";
import BookCharter from "./Pages/BookCharter";
import PageNotFound from "./Pages/404";
import Home from "./Pages/Home";
function App() {
const { id } = useParams();
console.log("useParams", id);
return (
<>
<header>
<img
src="../assets/Images/scsfcBadge.png"
alt="SoCal Sportfishing Club"
/>
SoCal Sportfishing Club
</header>
<div className="main">
<Router>
<aside className="left">
<Nav />
</aside>
<main>
<Routes>
<Route index element={<Home />} />
<Route path="/charters" element={<Charters />} />
<Route path="/landings" element={<Landings />} />
<Route path="/boats" element={<Boats />} />
{/* need to add parameter :id to link */}
<Route page="/bookcharter/" element={<BookCharter />} />
{/* need to add parameter :id to link */}
<Route page="/charterdetails/:id" element={<CharterDetails />} />
<Route page="*" element={<PageNotFound />} />
</Routes>
</main>
<aside className="right">
<Login />
</aside>
</Router>
</div>
<footer>Copyright © 2022 SoCal SportFishing Club </footer>
</>
);
}
export default App;
Home.js:
import React,{useState , useEffect} from 'react';
import { Link, useNavigate } from "react-router-dom";
import { BrowserRouter as Router, Route, Routes, useParams } from "react-router-dom";
function Home(){
const navigate = useNavigate();
const [charterData, setCharterData] = useState([]);
const [charterid, setCharterid] = useState('');
useEffect(() => {
// declare the async data fetching function
const fetchData = async () => {
fetch('http://localhost:5000/charter/featured/')
.then((response) => response.json())
.then((data) => setCharterData(data));
console.log('Charter ', charterData)
}
// call the function
fetchData()
// make sure to catch any error
.catch(console.error);
}, [])
function handleClick(charter) {
let id = charter.id;
let path = `/charterdetails//${id}`
navigate(path);
}
function BookClick(e) {
// e.preventDefault();
let path = `/bookcharter/${e.target.id}`
navigate(path);
}
return(
<div className="container">
{
charterData.map((charter, index) => {
return(<div key={index} className="card">
<div className="card-header">
</div>
<img src={'../assets/Images/charters/' + charter.Img} alt={charter.CharterName} />
<div className="tag tag-teal">{charter.BoatName} - {charter.Duration}</div>
<div className="card-body">
<div style={{fontSize:'28px', fontWeight: 'Bold'}}>
{charter.CharterName}
</div>
<p style={{fontSize:'16px'}}>Departure date: {new Date(charter.Departure).toDateString()}<br />
Return date: {new Date(charter.Return).toDateString()}<br />
Trip Duration: {charter.Duration}<br />
Price: ${charter.Cost}<br />
Max Load:{charter.MaxLoad}<br />
Target: {charter.Target}<br /></p>
<div style={{textAlign:'center', width: '100%'}}>
<Link
to= {{
pathname:`/charterdetails/${charter.id}`
}}
>
<button>Details</button>
</Link>
<button onClick={BookClick}>Book</button>
</div>
</div>
</div>)
})
}
</div>
)
}
export default Home;
Nav.js:
import React from 'react';
import { Link } from "react-router-dom";
export default function Nav() {
return (
<>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/landings">Landings</Link>
</li>
<li>
<Link to="/boats">Boats</Link>
</li>
<li>
<Link to="/charters">Club Charters</Link>
</li>
<li>
<Link to="/charterdetails">Charter Details</Link>
</li>
<li>
<Link to="/bookcharter">Book Charter</Link>
</li>
</ul>
</>
);
}
CharterDetails.js:
import React from 'react';
function CharterDetails(){
return(
<div>
Charter Details
</div>
)
}
export default CharterDetails;
BookCharter.js:
import React from "react";
function BookCharter(){
return(
<>
Book Charter
</>
)
}
export default BookCharter;
In the app.js I had page instead of path on the route.
Changed from
<Route page="/bookcharter" element={<BookCharter />} />
<Route page="/charterdetails/:id" element={<CharterDetails />} />
to
<Route exact path="/bookcharter" element={<BookCharter />} />
<Route exact path="/charterdetails/:id" element={<CharterDetails />} />
Goal:
Show the first page (default page) that contain a button that goes to the page with sidebar link Home and About using Router.
Problem:
Today, you have a menu with link Home and About but if I want a default page (that is the main page that you enter) and then you go to another page that has sidebar and using route.
How should it be created?
Info:
*Newbie in Reactjs
*The main page (default) should not contain any sidebar or any route.
Stackblitz:
https://stackblitz.com/edit/react-k19hye?
import React from 'react';
import './style.css';
import React, { Component } from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
const Nav = () => (
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</div>
);
const HomePage = () => <h1>Home Page</h1>;
const AboutPage = () => <h1>About Page</h1>;
export default class App extends Component {
constructor() {
super();
this.state = {
name: 'React',
};
}
render() {
return (
<Router>
{/* Router component can have only 1 child. We'll use a simple
div element for this example. */}
<div>
<Nav />
<Route exact path="/" component={HomePage} />
<Route path="/about" component={AboutPage} />
</div>
</Router>
);
}
}
render(<App />, document.getElementById('root'));
In order to set another default page, you should first update the route to HomePage to /home. And then define another route for the DefaultPage like <Route exact path="/" component={DefaultPage} />. In order to hide sidebar on the DefaultPage, you can use Switch to show only DefaultPage on route /.
You can take a look at this updated stackblitz forked from your original example for a live working example. Here is the final full code of this usage:
import React from 'react';
import './style.css';
import React, { Component } from 'react';
import { render } from 'react-dom';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
useHistory,
} from 'react-router-dom';
const Nav = () => (
<div>
<ul>
<li>
<Link to="/home">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</div>
);
const DefaultPage = () => {
const history = useHistory();
return (
<div>
<h1>Default Page</h1>
<button onClick={() => history.push('/main')}>go to main</button>
</div>
);
};
const HomePage = () => <h1>Home Page</h1>;
const AboutPage = () => <h1>About Page</h1>;
export default class App extends Component {
constructor() {
super();
this.state = {
name: 'React',
};
}
render() {
return (
<Router>
<Switch>
{/* Router component can have only 1 child. We'll use a simple
div element for this example. */}
<Route exact path="/" component={DefaultPage} />
<div>
<Nav />
<Route exact path="/home" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
</div>
</Switch>
</Router>
);
}
}
render(<App />, document.getElementById('root'));
In my react project, this is my App.js:
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Modal from "./Modal";
export default function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/modal">
<Modal />
</Route>
</Switch>
</div>
</Router>
);
}
function Home() {
return (
<div>
<h2>Home</h2>
<p>
Please <Link to="/modal/1">Click Here</Link> for see details.
</p>
</div>
);
}
When you click on "Click Here", the modal was open, but my home page will be disappear. how can open this modal without destroying the home page ?
DEMO HERE:
https://codesandbox.io/s/react-router-basic-2g9t1
Modals should not be in a route as they are supposed to be on top of another page, not a page themshelves. If you want my opinion I would suggest you to put the modal in any of the pages and control if it is opened or not with a react state:
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Modal from "./Modal";
export default function BasicExample() {
return (
<Router>
<div>
<Switch>
<Route exact path="/" component={Home} />
</Switch>
</div>
</Router>
);
}
const Home = () => {
const [ isModalOpened, setModalOpened ] = useState(false);
return (
<div>
<h2>Home</h2>
<button onClick={() => setModalOpened(!isModalOpened)}
<Modal isOpened={isModalOpened}>
...modal content here
</Modal>
</div>
);
}
And your modal component should look like something like this:
const Modal = ({ isOpened, children }) => (
<div>
{
isOpened &&
{ children }
}
</div>
)
If this helps you make sure to mark it as a good response!
My question might seem stupid because I don't have enough background in React JS.
I have this component:
import { BrowserRouter, Route, NavLink } from "react-router-dom";
import CourseInfo from "./CourseInfo";
import OneCourse from "./OneCourse";
class CourseList extends Component {
render() {
return (
<div>
<BrowserRouter>
<div className="row courses">
{this.props.corses.map(course => (
<NavLink key={course._id} to={`/courses/profile/${course._id}`}>
<OneCourse course={course} />
</NavLink>
))}
</div>
<Route
exact
path={`/courses/profile/:id`}
render={({ match }) => (
<CourseInfo
index={match.params.id}
course={
this.props.corses.filter(el => el._id === match.params.id)[0]
}
/>
)}
/>
</BrowserRouter>
</div>
);
}
}
When I click on OneCourse component, it shows me the CourseList component in the same page with the component CourseInfo added in the bottom.
How can I send user to a new page containing only CourseInfo, knowing that I have parameters to send from this component to CourseInfo?
I want to show CourseInfo component in a different page that doesn't contain the CourseList
<NavLink> is just fine. For the rest, you might use the <Switch> component:
import { BrowserRouter, Route, NavLink, Switch } from 'react-router-dom';
class CourseList extends Component {
render() {
return (
<div>
<BrowserRouter>
<Switch>
<Route
exact
path={`/`} render={({ match }) => (
<div className="row courses">
{this.props.corses.map(course => (
<NavLink key={course._id} to={`/courses/profile/${course._id}`}>
<OneCourse course={course} />
</NavLink>
))}
</div>
)}
/>
<Route
exact
path={`/courses/profile/:id`}
render={({ match }) => (
<CourseInfo
index={match.params.id}
course={
this.props.corses.filter(el => el._id === match.params.id)[0]
}
/>
)}
/>
</Switch>
</BrowserRouter>
</div>
);
}
}
Quoting from the docs:
Switch is unique in that it renders a route exclusively. In contrast, every that matches the location renders inclusively.
With complex routing the render props approach gets confusing. Moving the routing to a separate component is a better approach:
import React from 'react';
import { BrowserRouter, Route, Link, Switch } from "react-router-dom";
import CourseList from './CourseList';
import Course from './Course';
function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={CourseList} />
<Route exact path="/courses/profile/:id" component={Course} />
</Switch>
</BrowserRouter>
);
}
export default App;
Then your CourseInfo component looks like:
class CourseList extends Component {
render() {
return (
<div>
<div className="row courses">
{this.props.corses.map(course => (
<NavLink key={course._id} to={`/courses/profile/${course._id}`}>
<OneCourse course={course} />
</NavLink>
))}
</div>
</div>
);
} }
The official documentation provides plenty examples.
I have an website with this structure:
<Header>
<MenuPrincipal>
<Home></Home>
</MenuPrincipal>
</Header>
When I click on a logo in the Header, it isn't working, nothing is happening and I would like to access the Home component The <Home> component is inside of <MenuPrincipal>. The <Header> component is the parent component, how you can see in the structure above. How can I solve it?
import React from 'react'
import { BrowserRouter as Router, Route, Link, } from 'react-router-dom'
import Home from './Home';
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import { showBGImage } from './actions';
const Header = (props) => {
return (
<div className="header">
<div>
<Router>
<div>
<h1>
<Link onClick={showBGImage} className="home-link" to='/'>Mauro Bitar<br />
<small className="home-link">arquiteto</small>
</Link>
</h1>
<Route exact path='/' render={() => <Home />} />
</div>
</Router>
</div>
</div>
)
}
export default Header
<BrowserRouter> it's more like a history browser, you need to use Switch instead.
import { BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom'
const Header = (props) => {
return (
<div className="header">
<Router>
<Switch>
<div>
<h1>
<Link onClick={showBGImage} className="home-link" to='/'>Mauro Bitar<br />
<small className="home-link">arquiteto</small>
</Link>
</h1>
<Route exact path='/' render={() => <Home />} />
</div>
</Switch>
</Router>
</div>
)
}