named path not working in react-router-dom react js - reactjs

I am using react-router-dom for routing purposes. This is my code:
//Libraries
import React from 'react';
import { Tabs, Tab } from 'react-tabify';
import { connect } from 'react-redux';
import {
BrowserRouter as Router,
Route,
withRouter
} from 'react-router-dom';
//Components
import HomePage from './containers/HomePage';
import PersonsPage from './containers/PersonsPage';
const App = () => (
<Router>
<div style={{height: '100%', width: '100%'}}>
<Route exact path="/" component={HomePage}/>
<Route exact path="/:id" component={PersonsPage}/>
// here i want to use like this --> <Route exact path="/personPage/:id" component={PersonsPage}/>
</div>
</Router>
)
export default withRouter(connect()(App));
Route exact path="/:id" component={PersonsPage}/> this works , but this Route exact path="/personPage/:id" component={PersonsPage}/> this didn't works for me . Can someone clarify/help me from this pls

I think you should simply wrap your routers in Switch component. But remember to put <Route exact path="/:id" component={PersonsPage}/> as last entry.
Here you have an example in one file:
import React, { Component } from 'react';
import { render } from 'react-dom';
import {
BrowserRouter as Router,
Route,
Switch,
Link,
withRouter
} from 'react-router-dom';
const HomePage = () => (
<div>
<h1>HomePage</h1>
<ul>
<li><Link to="/user/Tom">Tom</Link></li>
<li><Link to="/user/John">John</Link></li>
<li><Link to="/user/Andy">Andy</Link></li>
</ul>
</div>
);
const PersonsPage = (props) => (
<div>
<h1>Profile: {props.match.params.name}</h1>
</div>
);
class App extends Component {
render() {
return (
<Switch>
<Route exact path="/" component={HomePage}/>
<Route exact path="/user/:name" component={PersonsPage}/>
</Switch>
);
}
}
const AppWithRouter = withRouter(App);
render(
<Router>
<AppWithRouter />
</Router>
, document.getElementById('root')
);
Here you have link to working version https://stackblitz.com/edit/react-qqpraz

Related

functional component disappears while using react-router-dom

I just wanted to make a simple project setup with react-router-dom but whenever I'm using route the entire page becomes blank. my Nav disappears. why ?
there was a similar question for class component so it wasn't helpful for me.
App.js :
import "./App.css";
import Nav from "./components/Nav";
import Products from "./components/Products";
import About from "./components/About";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
function App() {
return (
<>
<Router>
<Nav />
<Route path="/about" component={About} />
<Route path="/products" component={Products} />
<About />
</Router>
</>
);
}
export default App;
Nav:
import React from "react";
import Navstyle from "../styles/Nav.module.css";
const Nav = () => {
return (
<nav className={Navstyle.Nav}>
<ul className={Navstyle.nav_links}>
<li>
Home
</li>
<li>
Products
</li>
<li>
About
</li>
</ul>
</nav>
);
};
export default Nav;
other components are just returning h2 tags
You need to use a layout (as a HOC) to add a navbar or other things to your code.
just use the components with routes in your router.
I recommend defining the Layout in another file.
export default function App() {
return (
<Layout>
<Router>
<Route component={Products} path="/products" exact />
<Route component={About} path="/about" exact />
</Router>
</Layout>
);
}
const Products = () => {
return <p>Products</p>;
};
const About = () => {
return <p>about</p>;
};
const Navbar = () => {
return <p>navbar</p>;
};
const Layout = ({ children }) => {
return (
<div>
<Navbar />
<div>{children}</div>
</div>
);
};
I find out ! the problem was YouTube videos I guess. first of all you must add BrowserRouter to your index.js not app.js , like this :
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
after that you must use react router in that way , not the way I tried first :
import "./App.css";
import Nav from "./components/Nav";
import Products from "./components/Products";
import About from "./components/About";
import { Route, Routes } from "react-router-dom";
function App() {
return (
<>
<Nav />
<Routes>
<Route path="/About" element={<About />} />
</Routes>
</>
);
}
export default App;
during the changes of react-router-dom in version 6 , this is the new way of using router.
the link of docs :
https://reactrouter.com/docs/en/v6/getting-started/overview

One router work but other router not work

Hey i have a reactjs app with this as app.tsx
import tw from 'twin.macro';
import { hot } from 'react-hot-loader/root';
import { Route, BrowserRouter as Router, Routes as Switch } from 'react-router-dom';
import Main from './Main';
import Test from './Test';
const App = () => {
return (
<><Main /><div css={tw`mx-auto w-auto`}>
<Router>
<Switch>
<Route path="/element" element={<Test />} />
<Route path="/" element={<Main />} />
</Switch>
</Router>
</div></>
);
};
export default hot(App);
But when i run a ./node_modules/.bin/webpack --watch --progress the localhost/ work but localhost/element not work i have a 404 error
Not Found The requested URL was not found on this server
Can you tell me why its not work?
(i use 6.2.1 of react-router-dom)
first and foremost you need to mention the version you are using , and try this if it works for u :-
your components should look like this, to work:-
import tw from 'twin.macro';
import { hot } from 'react-hot-loader/root';
import { Route, Routes} from 'react-router-dom';
import Main from './Main';
import Test from './Test';
const App = () => {
return (
<><Main /><div css={tw`mx-auto w-auto`}>
<Routes>
<Route exact path="/element" element= {<Test />} />
<Route exact path="/" element= {<Main/>} />
</Routes>
</div></>
);
};
NB: try to wrap your index.tsx component with the <BrowserRouter> </BrowserRouter> like this :
import { BrowserRouter } from "react-router-dom";
ReactDOM.render( <BrowserRouter> <App/> </BrowserRouter>, document.getElementById('root'))
therefore you can remove the BrowserRouter from the app.tsx
I think you're using ‘react-router-dom’ newer version. Switch is no longer in the new version. please read here
Switch' is not exported from 'react-router-dom'
import { Route, BrowserRouter as Router, Routes as Switch } from 'react-router-dom';
function App() {
const Main = () => {
return (
<h1>Main</h1>
)
}
const Test = <h1>Test</h1>
return (
<div >
<Router>
<Switch>
<Route path="/element" element={<Main />} />
<Route path="/" element={Test} />
</Switch>
</Router>
</div>
);
}
export default App;
You need to use the <Main /> structure

Error: useHref() may be used only in the context of a <Router> component

**When i Write my My Nav Bar Component Content Directly in My Router Component. It works Fine But When I write that content in a NavBar Component it Generates the following error
Error: useHref() may be used only in the context of a component.
.**
Im Using
"react-dom": "^17.0.2", "react-router-dom": "^6.0.0-beta.6",
Following are my Components..
My NavBar Component:-
import { Link } from "react-router-dom";
// import styles from './NavBar.module.css';
export const NavBar = () => {
return (
<nav>
<Link to="/"> Home </Link>
<Link to="/about"> About </Link>
<Link to="/product"> Product </Link>
</nav>
);
}
My Route Component:-
import { BrowserRouter as Router, Switch, Route, Routes} from "react-router-dom";
// importing Component's
import { Home } from "./Components/Home/Home";
import { About } from "./Components/About/About";
import { Products } from "./Components/Products/Products";
import { ProductItems } from "./Components/ProductItems/ProductItems";
import {NavBar} from "./Components/NavBar/NavBar";
import { Fotter } from "./Components/Fotter/Fotter";
export const RouterConfig = () => {
return (
<Router>
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route exact path="/product" component={Products} />
<Route path="/product/:id" component={ProductItems} />
<Route path="*" component={() => <h2>404 Not Found </h2>} />
</Switch>
{/* <Fotter />' */}
</Router>
);
};
import {BrowserRouter as Router} from "react-router-dom";
Use in components App.js or above in index.js and wrap your component in Router.
Then the problem will disappear ;-)
In Your case I see two option:
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById("root")
);
OR use App Component instead of RouterConfig Component.
App.js
import { BrowserRouter as Router, Switch, Route, Routes} from "react-router-dom";
// importing Component's
import { Home } from "./Components/Home/Home";
import { About } from "./Components/About/About";
import { Products } from "./Components/Products/Products";
import { ProductItems } from "./Components/ProductItems/ProductItems";
import {NavBar} from "./Components/NavBar/NavBar";
import { Fotter } from "./Components/Fotter/Fotter";
export const App = () => {
return (
<Router>
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route exact path="/product" component={Products} />
<Route path="/product/:id" component={ProductItems} />
<Route path="*" component={() => <h2>404 Not Found </h2>} />
</Switch>
{/* <Fotter />' */}
</Router>
);
};
I tried to explain it as best I could. Hope this helps you ;-) Best Greetings and Good Luck!
If you're still confused, check out here =>
React Router V6 - Error: useRoutes() may be used only in the context of a <Router> component
export is not running properly and causing an error. Can you retype it like below and try?:
import { Link } from "react-router-dom";
const NavBar = () => {
return (
<div>
<Link to="/"> Home </Link>
<Link to="/about"> About </Link>
<Link to="/product"> Product </Link>
</div>
);
}
export default Navbar;
Also, you don't need curly brace for import statement.
import NavBar from "./Components/NavBar/NavBar";
If problem still persists, you can check your file paths because you are repeating folder names twice, it looks suspicious to me. Maybe you mean this:
import NavBar from "./Components/NavBar";

How to stop random links from opening with react-router?

I am new to React and practicing with an online website for repairing appliances. I have used react-router and created all my routes in a separate file.
I have a problem though, I can open any link from the address bar like:
http://localhost:3000/<randomword>
I only want routes to be opened that I have declared in my routes component while if I type http://localhost:3000/something, I get an empty page with my header and footer in it.
here are my codes:
Index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import Routes from './Routes';
import './index.css';
const App = () => {
return(
<BrowserRouter>
<Routes />
</BrowserRouter>
)
}
ReactDOM.render(<App/>,document.getElementById('root'));
App.js:
import React, {Component} from 'react';
import { Route, BrowserRouter } from 'react-router-dom';
import Layout from './Containers/Layout';
import LandingPage from './Containers/Pages/LandingPage';
import About from './Containers/Pages/About';
import Cities from './Containers/Pages/Cities';
import Discount from './Containers/Pages/Discount';
class Routes extends Component {
render(){
return (
<div>
<Layout>
<BrowserRouter>
<Route path="/" render={props => <LandingPage {...props} />} exact component={LandingPage}/>
<Route path="/About" component={About}/>
<Route path="/Cities" component={Cities}/>
<Route path="/Discount" component={Discount}/>
</BrowserRouter>
</Layout>
</div>
);
}
};
export default Routes;
Layout.js:
import React, { Component } from 'react';
import Header from "./Layouts/Header";
import Footer from './Layouts/Footer';
import './Layout.css';
export default class Layout extends Component {
constructor(){
super();
this.state= {
}
}
render() {
return (
<div className="page-container">
<Header/>
<div className="content-wrap">
{this.props.children}
</div>
<Footer/>
</div>);
}
}
Can someone help me figure out how I should stop random random pages to be opened from addressbar?
Just want to start by saying I'm completely self-taught with React so I apologize if this answer is incorrect. However, in my experience with react-router I always have a Switch inside of my BrowserRouter. So your Routes class in app.js should something like this:
class Routes extends Component {
render(){
return (
<div>
<Layout>
<BrowserRouter>
<Switch>
<Route path="/" render={props => <LandingPage {...props} />} exact component={LandingPage}/>
<Route path="/About" component={About}/>
<Route path="/Cities" component={Cities}/>
<Route path="/Discount" component={Discount}/>
</Switch>
</BrowserRouter>
</Layout>
</div>
);
}
};
Just be sure you don't forget to update your imports to
import { Switch, Route, BrowserRouter } from 'react-router-dom';
import { Redirect } from "react-router-dom"
<Route path="/not-found" component={notFound-Component} />
<Redirect to="/not-found" />
This will always redirect you to 404 component if route is not present just make a 404 component and u should add the redirect at the end after all routes are defined

cannot read property history because it's undefined but it is

I am getting the error cannot read property history but I defined it.
This used the work when I had it in main.jsx in my client folder but now it stops working.
The app file is in my imports folder.
import { Router, Route, Switch, Redirect } from "react-router-dom";
import createBrowserHistory from "history/createBrowserHistory";
const history = createBrowserHistory();
// App component - represents the whole app
export class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="container">
<Router history={history}>
<Switch>
<Route path="/" exact component={Home} />
<Route
path="/dashboard"
render={() =>
this.props.currentUser ? <Dashboard /> : <NoPermission />}
/>
<Route path="/test" component={Test} />
<Route component={NotFound} />
</Switch>
</Router>
</div>
);
}
}
more info:
import createBrowserHistory from "history/createBrowserHistory";
within that file createBrowserHistory is the default export.
export.default = createBrowserHistory;
When trying BrowserRouter instead of router and deleting the history const and props I get following error in my console.
modules.js:26944 Uncaught TypeError: Cannot read property 'history' of undefined
at Link.render (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:26944)
at modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:18399
at measureLifeCyclePerf (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:17679)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:18398)
at ReactCompositeComponentWrapper._renderValidatedComponent (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:18425)
at ReactCompositeComponentWrapper.performInitialMount (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:17965)
at ReactCompositeComponentWrapper.mountComponent (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:17861)
at Object.mountComponent (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:10622)
at ReactDOMComponent.mountChildren (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:16977)
at ReactDOMComponent._createInitialChildren (modules.js?hash=b38005f7c50b72cb1ea0945090b4ba307f31282f:14176)
When using BrowserRouter in my main.jsx I can get it working. I can change URL's but the new views do not render. So I think there still is something wrong with the history. In this case I have not defined it but I am not receiving any errors. Any way how I can check or fix this?
import React from "react";
import { Meteor } from "meteor/meteor";
import { render } from "react-dom";
import "../imports/startup/accounts-config.js";
import App from "../imports/layouts/App.jsx";
import Test from "../imports/Test.jsx";
import { BrowserRouter } from "react-router-dom";
Meteor.startup(() => {
render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("render-target")
);
});
Going further on Kyle's answer I added withrouter to my test component.
import React, { Component } from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
class Test extends Component {
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
render() {
const { match, location, history } = this.props;
return (
<div>
<p>This is a test</p>
<p>
You are now at {location.pathname}
</p>
</div>
);
}
}
export default withRouter(Test);
I am using NavLinks to link to this route in my navigation bar component.
<NavLink to="/test" activeClassName="active">
Test
</NavLink>
However clicking those links does not render the test page. (the address in the URL bar does change). When I press refresh in the browser the page loads and the location.pathname shows the proper location.
If I remove the withrouter the functionality is the same.
I got it working by not using a component to nest the router in.
If somebody can explain me why I would greatly appreciate it.
import Navbar from "../components/Navbar.jsx";
import AccountsUIWrapper from "../components/AccountsUIWrapper.jsx";
//import pages
import Home from "../pages/Home.jsx";
import Dashboard from "../pages/Dashboard.jsx";
import Test from "../Test.jsx";
import NotFound from "../pages/NotFound.jsx";
import NoPermission from "../pages/NoPermission.jsx";
let currentUser = Meteor.user();
const App = () =>
<Router>
<div>
<Navbar currentUser={currentUser} />
<AccountsUIWrapper />
<p>
{currentUser ? currentUser._id : "current user id not found"}
</p>
<Switch>
<Route exact path="/" component={Home} />
<Route
path="/dashboard"
render={() => (currentUser ? <Dashboard /> : <NoPermission />)}
/>
<Route path="/test" component={Test} />
<Route component={NotFound} />
</Switch>
</div>
</Router>;
export default App;
React Router 4 has history baked into it. You can see from the documentation for BrowserRouter, HashRouter, and MemoryRouter that there is no argument for history.
If you would like to access history in React Router v4 you should use the withRouter HoC on the component that you wish to have access to it in. withRouter will make ({match, history, location }) available inside any component that it wraps.
As you can see from this line of code: var _createBrowserHistory = require('history/createBrowserHistory'); which is line 13 in BrowserRouter.js and HashRouter.js history is already included for you. It is also included in the memory router on line 9 of MemoryRouter.js.
Try changing your import at the top to import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom"; and then remove history={ history } from <Router />.
EDIT: Please take a look at the documentation for React Router 4. Here is a basic example.
Here is a post of the code incase the link ever goes dead.
import React from 'react'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
)
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
const About = () => (
<div>
<h2>About</h2>
</div>
)
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic}/>
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
)
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
export default BasicExample

Resources