I'm working on a simple web app with Horizon and React to learn more about web design.
For some reason, my Router will not Route to various sub directories. For instance, I get my Layout page when I visit localhost:8181/, but when I visit localhost:8181/Home, I get (displayed in the webpage in Firefox) 'File "dist\Home" not found."
I also get this code in the Firefox console:
The character encoding of the plain text document was not declared.
The document will render with garbled text in some browser
configurations if the document contains characters from outside the
US-ASCII range. The character encoding of the file needs to be
declared in the transfer protocol or file needs to use a byte order
mark as an encoding signature.
Here is my Router Code:
//Routing.jsx
import React from 'react'
import { Router, Route, Link, browserHistory, IndexRoute, IndexRedirect } from 'react-router'
//Routes:
import MainLayout from './components/MainLayout.jsx'
import Search from './components/Search.jsx'
import PickFilm from './components/PickFilm.jsx'
import Login from './components/Login.jsx'
import Home from './components/Home.jsx'
export const Routing = () => {
return (
<Router history={browserHistory}>
<Route path = "/" component = {MainLayout} >
<Route path = "/Home" component = {Home} />
<Route path = "/Search" component = {Search} />
<Route path = "/PickFilm" component = {PickFilm} />
</Route>
<Route path = "/Login" component = {Login} />
</Router>
)
}
Here is my Index code:
//Index.jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { Routing } from './Routing.jsx'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
// Routing Information
ReactDOM.render((
<MuiThemeProvider>
<Routing />
</MuiThemeProvider>
), document.getElementById('root'));
Here is my component for Home:
//components/Home.jsx
import React, { Component } from 'react'
export default class Home extends Component {
render() {
return (
<span>You're home.</span>
)
}
}
Here is my component for the Layout:
//components/MainLayout.jsx
import React, { Component } from 'react'
import Navbar from './Navbar.jsx'
//Needed for onTouchTap
//http://stackoverflow.com/a/34015469/988941
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
export default class MainLayout extends Component {
render() {
return(
<div>
<Navbar />
</div>
);
}
}
Like I said, the layout will render when visiting localhost:8181/. But I get that error when visiting any of the subcomponents, such as localhost:8181/Home. Where am I going wrong?
I'm using these software versions:
babel-core: 6.10.4 (+ plugins and presets for react & es2015),
webpack 1.13.1,
Horizon 1.1.3,
material-ui 0.15.2,
React 15.2.1,
React-router 2.5.2.
You forgot to include {this.props.children} inside the render method of MainLayout so your child routes aren't being rendered at all.
Related
I've read some answers here and it seems they are all replying to a specific problem. Mine more about usage and placement rather than a problem I am facing. I also read the documentation but it does not answer my question.
My question is where to use react-router components?
Do I import (and use) BrowserRouter in index.js or App.js or does it go wherever the navigation bar is?
Do Route, Switch, NavLink, Link must be in the same module/file? If not, do I use them around the navigation bar element?
On the official website it shows that <Switch> is INCLUDED within <BrowserRouter> tags AFTER <Link> elements were used. Can I conclude from that <Switch> always come in the same element where <Link> elements were used?
I am beyond confused as to where these tags should be used in relation to other tags - not how to get them to work.
Finally, if I have a react app where index.js renders App.js. App.js is like a table of content of the main components I am rendering. Let's say: Header, Main, Footer. Inside the Header there are Greeting and then a NavigationBar. I want my links to be in the NavigationBar component as menu items. Where do I implement react-router components?
Thank you very much in advance.
1 . You can import and use BrowserRouter either in the root of the project which is index.js or in app.js just make sure it wraps around the Switch and Routes .
2 . The Switch Component must wrap all the Route components so this format is the most common way of using it :
<Switch>
<Route exact component={<Component />} path="/" />
</Switch>
You can use NavLink or Link almost anywhere in your components which are imported in Route component prop .
NavLink and Link is just for navigating between Routes in your app .
And for the last part you can have a Layout.js component to have Header Main and Footer components inside of it wrap all the other components which are used in Routes for example :
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// Router
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
,
document.getElementById('root')
);
App.js
import React from "react";
// Router
import { Switch, Route, withRouter } from "react-router-dom";
// Components
import Home from "./routes/Home/Home";
function App() {
return (
<Switch>
<Route exact component={Home} path="/" />
</Switch>
);
}
export default App;
Home.js
import React from "react";
// Router
import { NavLink } from "react-router-dom";
// Components
import Layout from "../../components/Layout/Layout";
function Home(props) {
return (
<Layout title="Homepage">
<NavLink to="/ss">ss</NavLink>
<NavLink to="/">/</NavLink>
</Layout>
);
}
export default Home;
Define Header Footer and Main in Layout.js :
Layout.js
import React, { Fragment } from "react";
import { Helmet } from "react-helmet";
// Components
import Header from "../Header/Header";
import Footer from "../Footer/Footer";
function Layout({ title, children }) {
return (
<Fragment>
<Helmet>
<title>
{title}
</title>
</Helmet>
<Header />
{children}
<Footer />
</Fragment>
);
}
export default Layout;
The children prop is basically the Home.js component which has Layout wrapper so the Home.js component will display Header Footer from layout and it's own content .
This is the most common way of using the react-router-dom in a react project .
Note
The Switch component will only render the first route that matches/includes the path. Once it finds the first route that matches the path, it will not look for any other matches. Not only that, it allows for nested routes to work properly, which is something that Router will not be able to handle.
Fragment is just for wrapping the component tags like this :
import React , { Fragment } from 'react';
function Component() {
return (
<Fragment>
<Other />
<Main />
</Fragment>
);
}
If you delete Fragment it will throw an error you can read more about Fragments here .
I am trying to get my react component to render in Meteor. I don't see any error messages or anything in the console, however, the component doesn't seem to display.
I am using react-router. I added log statements and it appears that the renderRoutes() function does get called, also, I see errors in the console when I change the directories for my imports (I get an error if I change the first import statement to import {Home} from '../home/blah'). I am not really sure what to try next.
Here is my router, which is in client/imports/lib/router.js.
import React from 'react';
import { Router, Route, Switch } from 'react-router';
import {createBrowserHistory} from 'history';
import {Home} from '../home/home';
import {Login} from '../login/login';
import {Connect} from '../connect/connect';
const browserHistory = createBrowserHistory();
export const renderRoutes = () => (
<Router history={browserHistory}>
<Switch>
<Route exact path="/" component={Home}/>
<Route exact path="/login" component={Login}/>
<Route exact path="/connect" component={Connect}/>
</Switch>
</Router>
);
Here is my home page. The other pages have a similar structure. The home page is in client/imports/home/home.js.
import React, { Component } from 'react';
export default class Home extends Component {
constructor(){
super()
this.state = {
}
}
render() {
return (
<div><h1>hello from the home page</h1></div>
);
}
}
Finally, this is my main.js. It's in client/main.js.
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import { renderRoutes } from './imports/lib/router.js';
import './main.html';
Meteor.startup(() => {
render(renderRoutes(), document.getElementById('app'));
});
Again, I don't see any error messages. The home page just doesn't render. I put console.log's in the constructor for the Home component and I do not see anything. I'm not sure if there is something about React that I am not understanding or if I need to change the way I am using the router.
Please let me know what I should try next, and if there is any more information I should include.
Thanks!
If you're exporting component using export default
export default class Home extends Component {
then you should import it this way:
import Home from '../home/home';
Read more about named and default exports
For the future - back to the source, check original code (from docs) first (usually working) - it's not hard to see the difference ;)
I'm trying to add routes to my react project. I have three separate components:
Window.js
import React, { Component } from 'react';
import SideBar from "../SideBar/SideBar";
import MainBody from "../MainBody/MainBody";
import { BrowserRouter as Router} from "react-router-dom";
class Window extends Component{
render() {
return (
<div>
<Router>
<SideBar />
<MainBody />
</Router>
</div>
);
}
}
export default Window
SideBar.js
import React, { Component } from 'react';
import PropTypes from "prop-types";
import { BrowserRouter as Link} from "react-router-dom";
class SideBar extends Component {
render() {
return(
<Link to="/">Home</Link>
<Link to="/about">About</Link>
);
}
}
export default SideBar;
MainBody.js
import React, { Component } from 'react';
import Home from "./Home/Home";
import About from "./About/About";
import { BrowserRouter as Route} from "react-router-dom";
class MainBody extends component {
render() {
return(
<div>
<Route exact path="/" component={Home}>
<Route path="/about" component={About}>
</div>
);
}
}
export default MainBody;
So basically, when I click one of my links in SideBar, I want to transition to that link in my Main Body (the Home and About just display their titles). However, When I run this, my Window, MainBody, and SideBar components work but my Home and About components do not get displayed. I've properly imported the router components into each component file. If I place the Routes from MainBody into the Window component, they get displayed (Not sure if the router links work with it though). Any suggestions would be helpful!
There are few typos in that snippets, dunno ifit was made when rewriting or u have it in your codebase, but be careful about them (component instead of Component, wrongly writtern render function with multiple elements returned etc).
import { BrowserRouter as Link} from "react-router-dom";
Theese imports are also wrong, You have to import Link not something as Link. You are only renaming import BrowserRouter to Link.
import { Link } from "react-router-dom";
And same for Route.
Here is example codesanbox . Let me know if that is what you wanted.
I came across the site https://hashnode.com/. When we click any topic it updates the URL and content without refreshing the site.
I know we can update the content using states and props without refresh.
How to change the URL at the same time?
Image
That's what React Router is for.
Routes.js
import React from 'react';
import {BrowserRouter,Switch,Route, withRouter} from 'react-router-dom';
import FirstPage from './pages/FirstPage';
import SecondPage from './pages/SecondPage';
class Routes extends React.Component {
render() {
return(
<Switch>
<Route exact path="/page-1" component={FirstPage} />
<Route exact path="/page-2" component={SecondPage} />
</Switch>
)
}
}
App.js
import React from 'react';
import store from "./Store";
import { Provider } from 'react-redux';
import Routes from "./Routes";
import {BrowserRouter} from 'react-router-dom';
class App extends React.Component
{
render()
{
return (
<Provider store={store}>
<BrowserRouter>
<Routes/>
</BrowserRouter>
</Provider>
)
}
}
export default App;
I am new to ReactJS. I need to have a common header and change title according to the route changes. Do I need to create a header.jsx file and import it? Or else, how can I render the header (common file) with route?
My routing part looks like this:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
import Home from './Home.jsx';
import { Router, Route, Link, browserHistory, IndexRoute } from 'react-router';
ReactDOM.render((
<Router history = {browserHistory}>
<Route path = "/home" component = {Home} />
<Route path = "/" component = {App}>
</Route>
</Router>
));
This should work:
header.jsx:
class Header extends Component {
render() {
return (<div>Your header</div>);
}
}
first-page.jsx:
class FirstPage extends Component {
render() {
return (<div>First page body</div>);
}
}
second-page.jsx
class SecondPage extends Component {
render() {
return (<div>Second page body</div>);
}
}
app.jsx:
import Header from './header.jsx';
class App extends Component {
render() {
return (
<div>
<Header />
{this.props.children}
</div>
);
}
}
web-app.jsx:
import App from './app.jsx';
import FirstPage from './first-page.jsx';
import SecondPage from './second-page.jsx';
ReactDOM.render(
<Router history = {browserHistory}>
<Route path = "/" component = {App}>
<Route path = "/first" component = {FirstPage}>
<Route path = "/second" component = {SecondPage}>
</Route>
</Router>
);
try this https://www.npmjs.com/package/react-helmet
import React from "react";
import Helmet from "react-helmet";
export default function Application () {
return (
<div className="application">
<Helmet title="My Title" />
...
</div>
);};
So if you need to display a common header among your routes, there's a couple ways of doing it. One is you can define your header inside its own component. Something simple for example:
import React from 'react';
export default React.createClass({
render() {
return <div className='header'><h1>{this.props.title}</h1></div>;
}
}
Then in your home component, app component, etc. Simply put inside your render(), after importing it at the top of each file.
The other option is to create your own sort of container component, still using the Header component we defined above:
import React from 'react';
export default React.createClass({
render() {
return (
<div className='container'>
<Header title={this.props.title} />
{this.props.children}
</div>
);
}
}
Then where you declare your routes:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
import Home from './Home.jsx';
import Container from './Container.jsx';
import { Router, Route, Link, browserHistory, IndexRoute } from 'react-router';
ReactDOM.render((
<Router history = {browserHistory}>
<Route path = "/home" component = {<Container title='home'><Home /></Container>} />
<Route path = "/" component = {<Container title='app'><App /></Container>}>
</Route>
</Router>
));
Admittedly i have not tried that second option. You might have to pass the router as a parameter from the container component down to its use of children component, if you want to do things like router.transitionTo('/path').
It's just an option if you don't want to repeat everywhere.