React-Router-Dom No effect when clicking <Link> - javascript

Presently I'm having an issue with my Navigation bar. When I click it it does not even change the URL address.
Note: I'm just using the lastest version of react and react-router-dom": ^4.4.0-alpha.1. No redux here.
Here is the index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import './index.scss'
import { BrowserRouter as Router } from 'react-router-dom'
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));
Here is my App.js I cut a lot out for brevity.
import React, { Component } from "react";
import { Route, Switch } from "react-router-dom";
import Home from "./Home";
import Form from "./Form";
import Navigation from "./Navigation";
import About from "./About";
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: null
};
}
render(props) {
return (
<div>
<Navigation
{...props}
isLoggedIn={this.state.isLoggedIn}
/>
<Switch>
<Route exact path="/" component={Home} />
<Route
path="/about"
render={() => {
return <About />;
}}
/>
<Route
path="/story/create"
render={(props )=> {
return <Form {...props} />;
}}
/>
</Switch>
</div>
);
}
}
export default App;
And Lastly, my Navigation.js
import React from "react";
import { Link } from "react-router-dom";
import Login from './Login'
import { Tab, Tabs } from "react-materialize";
export default function Navigation(props) {
const isLoggedIn = props.isLoggedIn;
let loggedState;
if (isLoggedIn) {
loggedState = (
<div>
<Tab title="Profile">
<Link to="/user/:id/profile">
Profile
</Link>
</Tab>
<Tab title="Log Out">
<Link to="/logout" onClick={props.handleLogOut}>
Log Out
</Link>
</Tab>
</div>
);
} else {
loggedState = (
<Tab title="Login">
<Login
isLoggedIn={props.isLoggedIn}
handleLogIn={props.handleLogIn}
/>
</Tab>
);
}
return (
<Tabs className="">
<Tab title="Home">
<Link to="/">
Home
</Link>
</Tab>
<Tab title="All Stories">
<Link to="/all_stories">
All Stories
</Link>
</Tab>
<Tab title="Write a Story">
<Link to="/story/create">
Write A Story
</Link>
</Tab>
{loggedState}
</Tabs>
)}
I think it would be helpful to mention that this issue is contain only to my navbar (functional) component. I have <Link>'s linking to other pages on my app they work just fine, it is only this one that is giving an issue.
I originally thought it was because I wasn't using withRouter, but after looking around on StackOverflow, it seems that that is only needed when using react-redux.
I have also, considered downgrading react-router-dom, but I couldn't find any other posts on this issue that mentioned that. It seems that most others only have this issue because they did not do Route exact path="/", but I think the way I did mine, it should still work correctly.
Thank you greatly in advance.

Probably, you're facing this issue because there is a click event listener with event.preventDefault() added to .tab or .tabs. You can fix it by taking one of the approaches below:
move Links outside of .tab / .tabs
get rid of preventDefault or remove tabs eventListener itself
use a tab component instead (for example react-tabs)
BTW, I don't see any need for tabs in your case.

Related

Routing in next.js

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.

React Js: <Link/> not working after build in gh-pages or netlify

I've built a react front end for my rest api. I've got them both deployed! However my navbar component has tags and do not work after clicking on them once. This happens in both netlify and gh-pages. Has anyone encountered this solution before? I am using HashRouter instead of ReactRouter. Thanks for taking your time with this :)
import React from "react";
import { Link } from "react-router-dom";
export default ({ context }) => {
const authedUser = context.authenticatedUser;
//Nav bar conditionally rendered on if the user is logged in or not
return (
<div>
<div className="header-div">
<div>
<Link to="/" className="header-div-left">
Student Courses
</Link>
</div>
<nav>
{authedUser ? (
<React.Fragment>
<div className="header-div-right">
<span className="header-div-right">
Welcome {authedUser.firstName} {authedUser.lastName}
</span>
<Link className="header-div-right" to="/signout">
Sign Out
</Link>
</div>
</React.Fragment>
) : (
<React.Fragment>
<div className="header-div-right-up-in">
<Link className="header-div-right" to="/signup">
Sign Up
</Link>
<Link className="header-div-right" to="/signin">
Sign In
</Link>
</div>
</React.Fragment>
)}
</nav>
</div>
</div>
);
};
import React from 'react';
import {
HashRouter as Router,
Route,
Switch
} from 'react-router-dom';
import './App.css';
import CourseDetail from './components/CourseDetail';
import Courses from './components/Courses';
import CreateCourse from './components/CreateCourse';
import Header from './components/Header';
import UpdateCourse from './components/UpdateCourse';
import UserSignIn from './components/UserSignIn';
import UserSignOut from './components/UserSignOut';
import UserSignUp from './components/UserSignUp';
import NotFound from './components/NotFound';
import PrivateRoute from './PrivateRoute';
import withContext from './Context';
//Connecting the SignUp & SignIn to context.
//This shares the data and actions throughout the component tree
/* Adding the const's as the component to the route handler
lets the components UserSignIn & UserSignUp gain access to
the function in context and any data or actions passed into
<Context.Provider value={value}> */
const UserSignInWithContext = withContext(UserSignIn);
const UserSignUpWithContext = withContext(UserSignUp);
const UserSignOutWithContext = withContext(UserSignOut);
/* To let the user know they are signed in
need to make changes to the name display in the end header */
const HeaderWithContext = withContext(Header);
const CoursesWithContext = withContext(Courses);
const CourseDetailsWithContext = withContext(CourseDetail);
const UpdateCourseWithContext = withContext(UpdateCourse)
const CreateCourseWithContext = withContext(CreateCourse)
export default () => (
<Router>
<div >
<HeaderWithContext/>
<Switch>
<Route exact path="/" component={CoursesWithContext} />
<PrivateRoute path="/courses/create" component={CreateCourseWithContext} />
<Route exact path="/courses/:id" component={CourseDetailsWithContext} />
<PrivateRoute path="/courses/:id/update" component={UpdateCourseWithContext} />
<Route path="/signin" component={UserSignInWithContext} />
<Route path="/signup" component={UserSignUpWithContext} />
<Route path="/signout" component={UserSignOutWithContext} />
<Route component={NotFound} />
</Switch >
</div >
</Router>
);

React Where to place login page for a one page app with a side menu

I have a react web app with a sidemenu. Whenever a user clicks on the link in the sidemenu, they are routed to a page that is rendered at the right side of the sidemenu. My question is, how do I do login for such a usecase seeing as any page I route to renders to the right of the sidemenu. I want the login page to be full screen without the side menu showing. This is what App.js looks like.
import React, { Component } from "react";
import { HashRouter } from "react-router-dom";
import Navigation from "./pages/General/components/Navigation";
import SideMenu from "./pages/General/components/SideMenu";
import "../src/css/App.css";
class App extends Component {
render() {
return (
<div>
<HashRouter>
<div className="main-wrapper">
<SideMenu />
<Navigation />
</div>
</HashRouter>
</div>
);
}
}
export default App;
Here is Navigation.js
import React from "react";
import { Route } from "react-router-dom";
import CalendarPage from "../../Calendar/CalendarPage";
import DoctorsList from "../../Doctors/DoctorsList";
import PatientsList from "../../Patients/PatientsList";
import AdminUsersList from "../../AdminUsers/AdminUsersList";
import SpecialitiesList from "../../Specialities/SpecialitiesList";
const Navigation = () => {
return (
<div className="mainarea">
<Route exact path="/" component={CalendarPage} />
<Route exact path="/scheduler" component={CalendarPage} />
<Route exact path="/doctors" component={DoctorsList} />
<Route exact path="/patients" component={PatientsList} />
<Route exact path="/admin-users" component={AdminUsersList} />
<Route exact path="/specialities" component={SpecialitiesList} />
</div>
);
};
export default Navigation;
The best solution I can figure out in terms of a clean design, is to implement another router in your App.jsx, because you are implementing the routing inside your component, and you need another one for your login page.
Then, your App.jsx could be like this:
import React, { Component } from "react";
import { Redirect, Route, Switch } from "react-router-dom";
import LogIn from "./pages/General/components/Login";
import HomePage from "./pages/General/components/HomePage";
import "../src/css/App.css";
class App extends Component {
render() {
return (
<div>
<Switch>
<Route path={'/login'} component={LogIn} />
<Route path={'/'} component={HomePage} />
<Redirect to="/" />
</Switch>
</div>
);
}
}
export default App;
Then, for your HomePage do the following
import React, { Component } from "react";
import { HashRouter } from "react-router-dom";
import Navigation from "./pages/General/components/Navigation";
import SideMenu from "./pages/General/components/SideMenu";
import "../src/css/App.css";
class HomePage extends Component {
render() {
return (
<div>
<HashRouter>
<div className="main-wrapper">
<SideMenu />
<Navigation />
</div>
</HashRouter>
</div>
);
}
}
export default HomePage;
I hope it helps!
Here is my solution, it not exactly a solution, but it will give you a basic idea on how to implement this.
The idea is to place the Login component in app.js, and conditionally display it if the user is logged in.
You will have to pass a handler function to login component through which you will be able to control app.js state.
When login will be sucessfull, u can show the Navigation and Sidemenu component.
import { Fragment } from "react";
import Login from "path/to/login";
class App extends Component {
state = { isLoggedIn: false };
loginHandler = () => {
this.setState({
isLoggedIn: true
});
};
render() {
return (
<div>
<div className="main-wrapper">
{isLoggedIn ? (
<Fragment>
<SideMenu />
<Navigation />
</Fragment>
) : (
<Login loginHandler={this.loginHandler} />
)}
</div>
</div>
);
}
}
Also you need write a separate router file, which will contain the main app.
This is used to show the app component when navigated to /
import React from 'react';
import { HashRouter, Route } from 'react-router-dom';
import App from './app';
const MainRoute = () => (
<HashRouter>
<Route path="/" component={App} />
</HashRouter>
);
export default MainRoute;

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-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