I upgraded from react Router v2 to v4 and then everything was broken! I searched on google with errors and learned a thing that is latest version of react router is totally re-written. I tried to follow the docs for updating my app. However I copied codes from official docs and it is working perfectly But when I'm working with my components and structure it's not routing. I couldn't figure out the actual problem. everything seems OK but still it's not routing.
Update
I did figure out the problem. it was with rendering the component from Route. I was using Component in my code but it should be component that's why my code wasn't working. It didn't event throw an error !
This code below is working for routing
import React from 'react';
import { render } from 'react-dom';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
const About = () => (
<div>About page</div>
)
const Home = () => (
<div>Home component</div>
)
const AppComponent = () => (
<div>App component is rendered as well</div>
)
render(
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route exact path="/" component={AppComponent}/>
<Route path="/about" component={About}/>
</div>
</Router>,
document.querySelector('#app')
)
This code below isn't working for routes
import React from 'react';
import { render } from 'react-dom';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
const SignUp = () => (
<div>This is Sign up Page</div>
)
const Home = () => (
<div>Home component</div>
)
const AppComponent = () => (
<div>App component is rendered as well</div>
)
render(
<Router>
<div className="container">
<nav className="navbar navbar-default">
<div className="container-fluid">
<div className="navbar-header">
<Link to="/" className="navbar-brand">Red Dice</Link>
</div>
<div className="collapse navbar-collapse">
<ul className="nav navbar-nav navbar-right">
<li><Link to="/signup">Sign up</Link></li>
</ul>
</div>
</div>
</nav>
<Route exact path="/" Component={Home} />
<Route exact path="/" Component={AppComponent} />
<Route path="/signup" Component={SignUp} />
</div>
</Router>,
document.querySelector('#app')
)
I have another question about browserHistory. In older version we had that but in newer version react router doesn't provide this. So what can I use in newer version to work with browserHistory?
In the newest version, you must use BrowserRouter to replace browserHistory option:
import { BrowserRouter } from 'react-router-dom'
<BrowserRouter>
<div> ... </div>
<Route />
<Route />
</BrowserRouter>
You can read more about this in https://reacttraining.com/web/api/BrowserRouter
Related
Trying to create an about page for a website im working on, I found this solution on Stack but it does not work for me. I was using an outdated tutorial for my original code, this is my current code:
About.js:
import React from "react";
import { Link, Route, useMatch } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
//const match = useMatch('/');
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to={'about-app'}>About App</Link>
</li>
<li>
<Link to={'about-author'}>About Author</Link>
</li>
</ul>
<Route path={':slug'}>
<SinglePage />
</Route>
</div>
);
};
export default About;
Index.js where I am rendering the component:
import React from "react";
import ReactDOM from "react-dom";
import TodoContainer from "./functionBased/components/TodoContainer"; // Component file
import "./functionBased/App.css"; // Style sheet
import { HashRouter as Router, Routes, Route } from "react-router-dom"; // Router file
import About from "./functionBased/pages/About";
import NotMatch from "./functionBased/pages/NotMatch";
ReactDOM.render(
<React.StrictMode>
<Router>
<Routes>
<Route exact path="/" element={<TodoContainer />} />
<Route path="/about/*" element={<About />} />
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
</React.StrictMode>,
document.getElementById("root")
);
Issues
The About component is directly rendering a Route component. The Route component can only be rendered by a Routes component or another Route component as a nested route.
The react-router-dom#6 Route components render their content on the element prop.
Solution
Import the Routes component and wrap the descendent Route component rendered by `About.
Render SinglePage on the route's element prop.
Example:
import React from "react";
import { Link, Routes, Route } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Routes>
<Route path=":slug" element={<SinglePage />} />
</Routes>
</div>
);
};
export default About;
Alternative
You could alternatively move the SinglePage route out to the main router as a nested route (instead of where it is as a descendent route).
Example:
import React from "react";
import { Link, Outlet } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Outlet />
</div>
);
};
export default About;
...
<Router>
<Routes>
<Route path="/" element={<TodoContainer />} />
<Route path="/about" element={<About />}>
<Route path=":slug" element={<SinglePage />} />
</Route>
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
You are defining the routes with /about/* and accessing them with about-something which does not exist at all, add \about\author in to for Link.
when i use link on my navbar component it changes the url but does not change the component, but it changes component when i reload,when i put link in main app.js it routes perfectly
app.js
import './App.css';
import Navbar from './Navbar/Navbar'
import About from './About/About'
import { Route, Link, BrowserRouter as Router ,Switch} from 'react-router-dom'
function App() {
return (
<div>
<Navbar/>
<Router>
<Link to="/about">about</Link>
<Switch>
<Route exact path="/about">
<About/>
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
navbar.js
import React from 'react'
import './Navbar.css'
import { Link, Router, BrowserRouter} from 'react-router-dom';
function Navbar() {
return (
<div>
<nav className="navbar">
<div>
<h1 className="nav_text">ExportGrains</h1>
</div>
<ul className="nav_ul">
<BrowserRouter>
<Link to="/about">about</Link>
<li id="nav_li">HOME</li>
<li id="nav_li">PRODUCTS</li>
<li id="nav_li">ABOUT</li>
<li id="nav_li">CONTACT</li>
</BrowserRouter>
</ul>
</nav>
</div>
)
}
export default Navbar
about.js
import React from 'react'
function About() {
return (
<div>
<h1>about page</h1>
</div>
)
}
export default About;
it would be very kind if you can help me with it
It should be
import About from "...."
....
....
<Route path="/about" exact component={About} />
You should use one single Router for all your routes. The problem is that navbar is using different router and your other components are inside another router. So remove the router inside navbar and use single router inside your app component.
Also you can add Navbar as default route and put it at the end of the switch so that it matches when none of the above routes are matching.
function App() {
return (
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Navbar />
</Route>
</Switch>
</Router>
);
}
Switch renders the first child <Route> or <Redirect> that matches the
location.
function Navbar() {
return (
<div>
<nav className="navbar">
<div>
<h1 className="nav_text">ExportGrains</h1>
</div>
<ul className="nav_ul">
<Link to="/about">about</Link>
<li id="nav_li">HOME</li>
<li id="nav_li">PRODUCTS</li>
<li id="nav_li">ABOUT</li>
<li id="nav_li">CONTACT</li>
</ul>
</nav>
</div>
);
}
I am trying to make a Navbar but the isn't re-directing to the given page. If I click any of the links in the Navbar, it would change the path in the url bar but won't re-direct to that page. I am not sure if I am missing anything. When I replace it with the tags, it works perfectly.
Navbar.js
import React from "react";
import { BrowserRouter as Router, Link, Switch } from "react-router-dom";
const Navbar = () => {
return (
<Router>
<Switch>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/articles">Articles</Link>
</li>
<li>
<Link to="/articles-all">All articles</Link>
</li>
</ul>
</nav>
</Switch>
</Router>
);
};
export default Navbar;
App.js
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import './App.css'
//pages
import Home from "./Pages/Home";
import About from "./Pages/About";
import Articles from "./Pages/Articles";
import ArticlesList from "./Pages/ArticlesList";
//components
import Navbar from './components/Navbar';
const App = () => {
return (
<div>
<Navbar/>
<Navigation />
</div>
);
};
export default App;
const Navigation = () => {
return (
<Router>
<div id="page-body">
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/articles" component={Articles} />
<Route path="/articles-all" component={ArticlesList} />
</div>
</Router>
);
};
Since you define the Router within Navigation and another one in Navbar your Links are not able to communicate to the Router Component in Navigation as they just communicate to their nearest parent Router component
You must you use a single Router instance to be able to perform seemless navigation within your App. Also a Switch component is not needed with Links but with Route
const App = () => {
return (
<Router>
<Router component={Navbar}/> // rendered as default route so that they receive router props
<Router component={Navigation} />
</Router>
);
};
export default App;
const Navigation = () => {
return (
<div id="page-body">
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/articles" component={Articles} />
<Route path="/articles-all" component={ArticlesList} />
</div>
);
};
const Navbar = () => {
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/articles">Articles</Link>
</li>
<li>
<Link to="/articles-all">All articles</Link>
</li>
</ul>
</nav>
);
};
export default Navbar;
Here's a working codesandbox URL https://codesandbox.io/s/frosty-black-3i8hp?file=/src/App.js
You were wrapping links with browserRouter and Switch. These APIs are intended to wrap Routes only.
So, It wasn't able to communicate well with your react app.
new to React Router, my question is how to render a particular component inside other layout which is already rendered (i have two components sidebar and content i just want if i click on any link in sidebar that component will we render in already render Content component not override that)
////////////Sidebar.js////////////
import React from 'react'
import { BrowserRouter, Link } from 'react-router-dom'
import PersonalImg from '../images/personal.gif'
const Sidebar = () => {
return (
<div className="sidebar">
<BrowserRouter>
<div className="personal-img">
<img src={PersonalImg} alt="personl-img" />
</div>
<div className="navigation">
<ul className="list">
<li><Link to="/about">About</Link></li>
<li><Link to="/work">Work</Link></li>
<li><Link to="/skills">Skills</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</div>
</BrowserRouter>
</div>
)
}
export default Sidebar;
Content component...
/////////////////Content.js//////////////////
import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import About from './About'
import Skills from './Skills'
import Work from './Work'
import Contact from './Contact'
const Content = (props) => {
return (
<div className="content">
<BrowserRouter>
<Route path="/" componet={About} />
<Route path="/work" componet={Work} />
<Route path="/contact" componet={Contact} />
<Route path="/skills" componet={Skills} />
</BrowserRouter>
</div>
)
}
export default Content;
and thats how App.js rendering these components
render() {
return (
<Fragment>
<Sidebar />
<Content />
</Fragment>
)
}
Here, I have created small demo for you
https://codesandbox.io/s/naughty-glade-vnj0l
Problem 1: componet spell is wrong. It should be component in the Route.
Problem 2: set exact keyword for the first route like this <Route exact path="/" componet={About} />.
Use single BrowserRouter throughout the application.
The component is not been displayed when I navigate to localhost:3000/signup
Is it because react router is updated to v4 and they way you route in react has now changed?
I have my main.js file
import Signup from '../imports/ui/Signup';
import
const routes = (
<Router history={browserHistory}>
<Route path="/signup" component={Signup}/>
</Router>
);
Signup component
import React from 'react';
export default class Signup extends React.Component {
render() {
return <p>Signup</p>
}
}
I'm using react router v4, also using Meteor.
React Router v4 is a re-write of React Router so you'll have to read the new API and adjust your code accordingly. I suggest going through all the examples which can be found here. Here's the basic example that looks similar to your code. The biggest thing you'll notice is you no longer have a centralized route config. Instead, you render `` s dynamically when you need them.
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