Routing in next.js - javascript

When I execute my program, it shows me this error:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
It's the first time I'm working with routes in next.js and I can't solve the error.
Index.js
import BgAnimation from '../components/BackgrooundAnimation/BackgroundAnimation';
import Hero from '../components/Hero/Hero';
import Projects from '../components/Projects/Projects';
import Contact from '../components/Contacts/Contact';
import Timeline from '../components/TimeLine/TimeLine';
import { Layout } from '../layout/Layout';
import { Section } from '../styles/GlobalComponents';
import { BrowserRoute as Router, Switch, Route } from 'react-router-dom'
const Home = () => {
return (
<Router>
<Layout>
<Section grid>
<Hero />
<BgAnimation />
</Section>
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={Timeline} />
<Route path="/contact" component={Contact} />
</Switch>
</Layout>
</Router>
);
};
export default Home;
Layout.js
import React from 'react'
import Header from '../components/Header/Header'
import { Container } from './LayoutStyles'
export const Layout = ({children}) => {
return (
<Container>
<Header/>
<main>{children}</main>
</Container>
)
}
Header.js
import Link from 'next/link';
import React from 'react';
import { AiFillGithub, AiFillInstagram, AiFillLinkedin } from 'react-icons/ai';
import { AiOutlineBook } from "react-icons/ai";
import { Container, Div1, Div2, Div3, NavLink, SocialIcons, Span } from './HeaderStyles';
const Header = () => (
<Container>
<Div1>
<Link href="/">
<a style={{ display:"flex", alignItems: "center", color: 'white', marginBottom:20}}>
<AiOutlineBook size="3rem"/><Span>Portfólio</Span>
</a>
</Link>
</Div1>
<Div2>
<Link href="#projects">
<NavLink>Projetos</NavLink>
</Link>
<Link href="#contact">
<NavLink>Contactos</NavLink>
</Link>
<Link href="#about">
<NavLink>Sobre mim</NavLink>
</Link>
</Div2>
<Div3>
<SocialIcons href="https://www.linkedin.com/in/sérgio-carreirinha/">
<AiFillLinkedin size="3rem"/>
</SocialIcons>
<SocialIcons href="https://github.com/SergioCarreirinha">
<AiFillGithub size="3rem"/>
</SocialIcons>
<SocialIcons href="https://www.instagram.com/sergio_carreirinha/">
<AiFillInstagram size="3rem"/>
</SocialIcons>
</Div3>
</Container>
);
export default Header;
Thanks for your time.

In Next.js we do not need to use react-router-dom package and its features like (BrowserRoute as Router, Switch, Route). Here you have the best source of information, I encourage you to read. Routing, router.
Next.js has a file-system based router built on the concept of
pages.
When a file is added to the pages directory it's automatically
available as a route.
Next.js router allows you to do client-side route transitions between
pages, similar to a single-page application.
A React component called Link is provided to do this client-side route
transition.

Related

React Routing with Navbar only showing blank screen [duplicate]

This question already has answers here:
Link tag inside BrowserRouter changes only the URL, but doesn't render the component
(2 answers)
Closed 10 months ago.
I have been trying to route to different pages in my react site but for some reason the whole page goes blank as soon as I add any routing. I am using npm and react bootstrap
Here is my code, I am trying to route to simple pages like Home.
App.js
import Artists from './Artists';
import Home from './Home';
import Music from './Music';
import Navigation from "./Navigation.js";
import 'react-bootstrap/dist/react-bootstrap.min.js';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Footer from './footer'
function App() {
return (
<div className="App">
<Router>
<Navigation></Navigation>
<Route exact path="/" component={Home}></Route>
<Route path="/artists" component={Artists}></Route>
<Route exact path="/music" component={Music}></Route>
</Router>
<Footer/>
</div>
);
}
export default App;
Navigation.js
import React from "react";
import { Button, Navbar, Container} from 'react-bootstrap'
import { Link, Router, Route } from "react-router-dom";
import Nav from "react-bootstrap/Nav";
import { LinkContainer } from "react-router-bootstrap";
import Artists from './Artists'
import Home from './Home'
const Navigation = () => {
return (
<Navbar bg="light" variant="light">
<Navbar.Brand>
<img src={require('.//Nothing Iconic Reccords.png')} width="135"
height="135"/>
</Navbar.Brand>
<Nav className="nav-link">
<LinkContainer to="/">
<Nav.Link>Home</Nav.Link>
</LinkContainer>
<LinkContainer to="/artists">
<Nav.Link>Artists</Nav.Link>
</LinkContainer>
<LinkContainer to="/music">
<Nav.Link>Music</Nav.Link>
</LinkContainer>
</Nav>
</Navbar>
);
};
export default Navigation;
Try using routes, put route in routes and add props element in route:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/artists" element={<Artists />} />
<Route path="/music" element={<Music />} />
</Routes>
</Router>
For react router 5 or below
You're missing an important wrapper called <Switch> that wraps around your routes (<Route> elements), in your App.js file. Here's the quickstart guide describing the structure.
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
</Switch>
</Router>
Without this wrapper (or similar ones as described in the documentation) , react router doesn't know what matching logic you want to apply, so it can't render a specific page/route.
If you are using React router 6 (most recent version), the entire syntax needs to be re-written.
For React router 6 (most recent version)
The you have to order your routes like so:
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}/>
</Routes>
</BrowserRouter>
This is link goes more in-depth about this
You need to carefully read the react-router-dom documentation. According to the documentation,
If you're using the latest version of react-router-dom i.e. #6.3.0, you must use { Routes } instead of { Switch }. Otherwise, you're good to go with { Switch } for older versions of react-router-dom.
You must import { BrowserRouter as Router, Switch, Route } from "react-router-dom" in your App.js file.
You only need to wrap your respective routes inside the Router element and leave everyother component outside of element i.e. component.
You need to write your components in the form of HTML elements inside tag.
Your App.js file should look as same as the one below:
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Artists from './Artists';
import Home from './Home';
import Music from './Music';
import Navigation from "./Navigation.js";
import 'react-bootstrap/dist/react-bootstrap.min.js';
import Footer from './footer'
export default function App() {
return (
<Router>
<div>
<Navigation/>
<Switch>
<Route exact path="/" component={<Home />} />
<Route path="/artists" component={<Artists />} />
<Route exact path="/music" component={<Music />} />
</Switch>
</div>
</Router>
);
}
export default App
If you want to get a specific component on some action e.g. onClick, like inside a navigation component, you only need to import { LinkContainer } or { Link } from "react-router-dom", because Link and LinkContainer, both behave the same way. So you don't need to import both of them at a time in a single file. Importing Router and Route make no sense in the Navigation.js file. Since you are not making any use of the Artist and Home components inside the Navigation.js file, you are not required to import them into Navigation.js.
Your Navigation.js file should look as same as the one below:
import { link } from "react-router-dom"
import React from "react";
import { Button, Navbar, Container} from 'react-bootstrap'
import Nav from "react-bootstrap/Nav";
const Navigation = () => {
return (
<Navbar bg="light" variant="light">
<Navbar.Brand>
<img src={require('.//Nothing Iconic Reccords.png')} width="135"
height="135"/>
</Navbar.Brand>
<Nav className="nav-link">
<LinkContainer to="/">
<Nav.Link>Home</Nav.Link>
</LinkContainer>
<LinkContainer to="/artists">
<Nav.Link>Artists</Nav.Link>
</LinkContainer>
<LinkContainer to="/music">
<Nav.Link>Music</Nav.Link>
</LinkContainer>
</Nav>
</Navbar>
);
};
export default Navigation;

React link updates URL but page doesn't change/render

I am importing a header into the main.jsx file below as a simple component (SFC) that acts as a navigation menu. Everything looks fine and clicking on the menu does update the URL in the browser. However the application does not change page. I have googled a bit and come across various posts suggesting its related to a blocking update but I don't know how to fix it.
Full source is here: https://github.com/infornite/n4nite-react-ui-aug-2018
src/component/layout/header.tsx
import * as React from 'react'
import { Link } from 'react-router-dom'
import { Layout, Menu } from 'antd'
import '../../style/index.less';
const { Header } = Layout;
interface HeaderProps {
className?: string
}
const nHeader: React.SFC<HeaderProps> = () => (
<Header>
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['1']}
style={{ lineHeight: '64px' }}
>
<Menu.Item key="1">
<Link to="/">Index</Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/register">Register</Link>
</Menu.Item>
</Menu>
</Header>
)
export default nHeader
src/routes.tsx
import * as React from 'react'
import { Route, Switch } from 'react-router-dom'
import IndexPage from './pages'
import RegisterPage from './pages'
const Routes: React.SFC = () => (
<Switch>
<Route exact path="/" component={IndexPage} />
<Route path="/register" component={RegisterPage} />
<Route component={() => <div>Not Found</div>} />
</Switch>
)
export default Routes
src/main.tsx
import * as React from 'react'
import { Provider, connect } from 'react-redux'
import { ConnectedRouter } from 'connected-react-router'
import { Store } from 'redux'
import { History } from 'history'
import Routes from './routes'
import { ApplicationState } from './store'
import { Layout } from 'antd'
import './style/index.less';
import Header from './components/layout/header'
import Breadcrumb from './components/layout/breadcrumb'
import Footer from './components/layout/footer'
const { Content } = Layout;
// Separate props from state and props from dispatch to their own interfaces.
interface PropsFromState {
}
interface PropsFromDispatch {
[key: string]: any
}
// Any additional component props go here.
interface OwnProps {
store: Store<ApplicationState>
history: History
}
// Create an intersection type of the component props and our Redux props.
type AllProps = PropsFromState & PropsFromDispatch & OwnProps
class Main extends React.Component<AllProps> {
public render() {
const { store, history } = this.props
return (
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Layout className="layout">
<Header />
<Content style={{ padding: '0 50px' }}>
<Breadcrumb />
<div style={{ background: '#fff', padding: 24, minHeight: 280 }}>
<Routes />
</div>
</Content>
<Footer/>
</Layout>
</div>
</ConnectedRouter>
</Provider>
)
}
}
// It's usually good practice to only include one context at a time in a connected component.
// Although if necessary, you can always include multiple contexts. Just make sure to
// separate them from each other to prevent prop conflicts.
const mapStateToProps = () => ({
})
// Normally you wouldn't need any generics here (since types infer from the passed functions).
// But since we pass some props from the `index.js` file, we have to include them.
// For an example of a `connect` function without generics, see `./containers/LayoutContainer`.
export default connect<PropsFromState, PropsFromDispatch, OwnProps, ApplicationState>(
mapStateToProps
)(Main)
The issue was a silly mistake on my part where I was importing the same page (e.g. my Index page) as both the index page and the register page. Everything was actually working fine but because of this mistake React was loading the same page when I went to either link. I was too quick to assume I had a complex problem and started looking at Blocked Components and HOC's when it was actually a very simple issue.
Wrong: src/routes.tsx
import IndexPage from './pages'
import RegisterPage from './pages'
Correct: src/routes.tsx
import IndexPage from './pages/index'
import RegisterPage from './pages/register'
you've missed the keyword "exact", change your router to:
<Route exact path="/register" component={RegisterPage} />
also, surround it with BrowserRouter

React Router doesn't display component when route is matched (but render works)

I am trying to learn React and using Create-React-App to experiment.
Today I was trying to learn how to use React Router, but I couldn't make it work.
Here is my code: (App.js)
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import { BrowserRouter as Router, Route, Link, NavLink, Switch } from 'react-router-dom'
import { Navbar, Jumbotron, Button } from 'react-bootstrap';
class App extends Component {
render() {
const baseUrl = process.env.PUBLIC_URL;
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">React Star Wars Table Test</h1>
</header>
<Router>
<div>
<NavLink to={baseUrl + '/Foo'}>Foo</NavLink> <NavLink to={'/Bar'}>Bar</NavLink>
<hr />
<Switch>
<Route path="/" exact render={() => (<h1>HOME</h1>)} />
<Route path={baseUrl + "/Foo"} exact Component={Foo} />
<Route path='/Bar' exact Component={Bar} />
</Switch>
</div>
</Router>
</div>
);
}
}
class Foo extends Component {
render() {
return (
<p>Foo!</p>
);
}
}
class Bar extends Component {
retnder(){
return (
<h1>Bar!</h1>
);
}
}
export default App;
The issue is that the routes don't display the components when they match the URL (either clicking on the NavLinks or manually typing the URL).
The base ('/') route works and displays the HOME H1.
I know the routes are matching because if I try to use the render attribute for all the routes, it works.
No compile errors, no console errors.
The sample code contains the Switch tag, but I have tried also
without, same result.
The sample code has a NavLink and a Route with
a baseUrl const and one without, I have tried either way (none, both,
one yes and one not), same result.
The prop of Route that takes a component is called component, not Component with a capital c.
<Route path='/Bar' exact component={Bar} />

React Router v4 not rendering components

Having an issue with React Router v4 rendering components. On initial load of the application it will render the correct component corresponding to the URL However, any subsequent Link clicks will not render the desired component.
Libraries
React Router: 4.2.2
React: 15.6.1
React DOM: 15.6.1
-- just to mention libraries in case of impact --
React Redux: 5.0.6
Redux: 3.7.2
Material UI: 0.19.0
Going to omit some imports for sake of brevity
Site Structure
index.jsx
|
App.jsx
|
Auth.jsx
|
Layout.jsx
<Routes />
index.jsx
import React from 'react';
import store from './store.js';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory';
const history = createBrowserHistory();
import App from './containers/App.jsx';
ReactDOM.render(
<Provider store={store}>
<MuiThemeProvider muiTheme={muiTheme}>
<BrowserRouter>
<App />
</BrowserRouter>
</MuiThemeProvider>
</Provider>,
document.getElementById('root')
);
App.jsx
import React, { Component } from 'react';
import Auth from '../components/Auth.jsx';
class App extends Component {
render() {
return <Auth />;
}
}
Auth.jsx
import React from 'react';
import { Route } from 'react-router-dom';
import Layout from './Layout.jsx';
export default function Auth(props) {
//this Has a render function to render a Loader, Error Page, or the Layout
return <Layout />;
}
Layout.jsx
There's more complexity involved here with rendering out the entire application. I'm going to leave the other layout components commented out and just have some Links and a Switch component to get that working before making items more modular.
import React, { Component } from 'react';
import { Link, Switch, Route } from 'react-router-dom';
import Overview from './views/overview/Overview.jsx';
import Home from './views/home/Home.jsx';
export default class Layout extends Component {
render() {
return (
<div className="layout">
{/* <TopBar /> */}
{/* <AppBar/> */}
{/* <Drawer>
<MainMenu/>
</Drawer> */}
<Link to="/">HOME</Link>
<Link to="/overview">Overview</Link>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/overview" component={Overview} />
</Switch>
{/* <Routes /> */}
{/* <Footer /> */}
</div>
);
}
}
Routes.jsx
This is what I'm intending the routes components to look like.
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Home from './views/home/Home.jsx';
import Overview from './views/overview/Overview.jsx';
import Admin from './views/admin/Admin.jsx';
import NotFound from './NotFound.jsx';
export default function Routes(props) {
return (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/overview" component={Overview} />
<Route path="/admin" component={Admin} />
<Route component={NotFound} />
</Switch>
);
}
Is there something I'm missing to get components to render clicking Link? I'm not getting any console errors or anything telling me there's an issue. So not sure if components are not wrapped correctly or what may be causing the issue.
Looks like what was happening is that with Redux integrations was blocking updates.
Need to:
import {withRouter} from 'react-router-dom';
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App))'
Documentation
You can also use pure: false in connect.
https://github.com/reactjs/react-redux/blob/master/docs/troubleshooting.md#my-views-arent-updating-when-something-changes-outside-of-redux

React-Router-Redux and React-Bootstrap

I've been battling this one for a while!
I want to have the 'main app container' which always has the logo, navigation... I want to use react-bootstrap to pretty it up.
At the moment I'm running into problems, my project is based off davezuko's "react-redux-starter-kit"
I tried putting all of my bootstrap <NavBar> and <LinkContainers> in the Root container inside the provider.
Everything shows up and looks nice but none of my links work, and when I put a regular react-router <Link> I would run into the same problems.
I figured, well, links work in the views which is called by routes, so I copied all of this into the routes after
export default (store) => (
Babel, eslint and webpack allow this to compile, but when I run the page none of this shows up, and when I take a look the react-dev console, these react nodes don't even appear.
Here's what I have, Root.js:
import React, { PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import { IndexLink, Link } from 'react-router';
import NavBar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
export default class Root extends React.Component {
static propTypes = {
history: PropTypes.object.isRequired,
routes: PropTypes.element.isRequired,
store: PropTypes.object.isRequired
};
get content () {
return (
<Router history={this.props.history}>
{this.props.routes}
</Router>
);
}
get devTools () {
if (__DEBUG__) {
if (__DEBUG_NEW_WINDOW__) {
if (!window.devToolsExtension) {
require('../redux/utils/createDevToolsWindow').default(this.props.store);
} else {
window.devToolsExtension.open();
}
} else if (!window.devToolsExtension) {
const DevTools = require('containers/DevTools').default;
return <DevTools />;
}
}
}
render () {
const styles = require('./../containers/Root.scss');
return (
<Provider store={this.props.store}>
<div>
<div className={styles.Root}>
<Link to='login'>login</Link>
<NavBar fixedTop>
<NavBar.Header>
<NavBar.Brand>
<IndexLink to='/' activeStyle={{color: '#33e0ff'}}>
<div className={styles.brand}></div>
<span>Hero Energy Solutions</span>
</IndexLink>
</NavBar.Brand>
<NavBar.Toggle />
</NavBar.Header>
<NavBar.Collapse eventKey={0}>
<Nav navbar>
<LinkContainer to='/chat'>
<NavItem eventKey={1}>Chat</NavItem>
</LinkContainer>
<LinkContainer to='/widgets'>
<NavItem eventKey={2}>Widgets</NavItem>
</LinkContainer>
<LinkContainer to='/survey'>
<NavItem eventKey={3}>Survey</NavItem>
</LinkContainer>
<LinkContainer to='/about'>
<NavItem eventKey={4}>About Us</NavItem>
</LinkContainer>
<LinkContainer to='/'>
<NavItem eventKey={5}>Login</NavItem>
</LinkContainer>
</Nav>
</NavBar.Collapse>
</NavBar>
</div>
{this.content}
{this.devTools}
</div>
</Provider>
);
}
}
Routes.js:
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import CoreLayout from 'layouts/CoreLayout/CoreLayout';
import HomeView from 'views/HomeView/HomeView';
import LoginView from 'views/LoginView/LoginView';
import NotFoundView from 'views/NotFoundView/NotFoundView';
import RestrictedView from 'views/RestrictedView/RestrictedView';
import AboutView from 'views/AboutView/AboutView';
import { IndexLink, Link } from 'react-router';
import NavBar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
import {UserAuthWrapper} from 'redux-auth-wrapper';
import {routerActions} from 'react-router-redux';
const CheckAuth = UserAuthWrapper({
authSelector: (state) => state.user, // how to get the user state
redirectAction: routerActions.replace, // the redux action to dispatch for redirect
wrapperDisplayName: 'CheckAuth', // a nice name for the auth check
failureRedirectPath: 'login' // default anyway but meh!
});
export default (store) => (
<div>
<Route path='/' component={CoreLayout}>
<IndexRoute component={HomeView} />
<Route path='login' component={LoginView} />
<Route path='home' component={HomeView} />
<Route path='about' component={AboutView} />
<Route path='restricted' component={CheckAuth(RestrictedView)} />
</Route>
<Route path='*' component={NotFoundView}/>
</div>
);
I'm not sure if this is of much help but here's a screen shot of the client side with the react console. Screenshot of react dev console:
Sorry everyone! The solution is extremely simple.
The CoreLayout View, is where all of this stuff is supposed to go. My biggest problem was not properly understanding how react-router works! Now that I understand, here's the reasoning:
The Route / matches all requests that have a / in it (which is basically all requests). But it is a React Component, that contains other React Components! So the CoreLayout component is returned, but the content of CoreLayout is the corresponding View, i.e. About, Home...
Edit:
You need to include <div> {this.props.children} </div>
In the CoreLayout View where you want your other sub-views to be rendered (otherwise they won't render!).

Categories

Resources