Wrapper Component showing different navigation on different pages - reactjs

I'm trying to make my page flexible to show different navigation bars depending on the page I'm on. When I run the page with the code presented below it shows the different navs as they should, but the actualRouteComponent is not showing the content of the route component eg. FrontpageRoute, BookRoute.
This is my App.js:
import React from 'react';
import {BrowserRouter as Router, Switch} from 'react-router-dom';
import './Mystyles.scss';
//Routes
import DynamicLayout from './layout/DynamicLayout'
import FrontpageRoute from './routes/FrontpageRoute';
import BookRoute from './routes/BookRoute';
function App() {
return (
<Router>
<div className="App">
<Switch>
<DynamicLayout
exact
path="/"
component={FrontpageRoute}
/>
<DynamicLayout
exact
path="/book"
component={BookRoute}
layout="SUB_NAV"
/>
</Switch>
</div>
</Router>
);
}
export default App;
This is my DynamicLayoutRoute.js:
import React from 'react';
import {BrowserRouter as Route} from 'react-router-dom';
import Header from './../components/Header';
import MainNavigation from '../components/MainNavigation';
const DynamicLayout = props => {
const { component: RoutedComponent, layout, ...rest } = props;
const actualRouteComponent = (
<Route
{...rest}
render={props => (
<RoutedComponent {...props} />
)}
/>
);
switch (layout) {
case 'MAIN_NAV': {
return (
<div>
<MainNavigation />
<Header />
{actualRouteComponent}
</div>
)
}
case 'SUB_NAV': {
return (
<div>
<MainNavigation />
<h2>Sub Nav</h2>
<Header />
{actualRouteComponent}
</div>
)
}
default: {
return (
<div>
<MainNavigation />
<Header />
{actualRouteComponent}
</div>
)
}
}
};
export default DynamicLayout;
and here is my MainNavigation.js:
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'
class MainNavigation extends Component {
render() {
return (
<nav className="main-navigation">
<div className="main-navigation--content">
<div className="mobil-nav">
<span>Burger</span>
</div>
<div className="link-list">
<NavLink exact to="/">Frontpage</NavLink>
<NavLink exact to="/book">Book</NavLink>
</div>
<div className="social">
<span>Instagram</span>
</div>
</div>
</nav>
)
}
}
export default MainNavigation
Can someone tell me what is wrong?

I see that in your DynamicLayoutRoute component you are accessing props as this.props. this is undefined in functional components.
Access props like this -
const DynamicLayoutRoute = props => {
const { component: RoutedComponent, layout, ...rest } = props;
...
}

Related

How to redirect to completely new page after user click in react?

I have a parent component which is rendering some stuff and a child component which is getting some props from parent component. And when user click button in Parent then it should redirect to completely new Page of child componen.
Parent Component
import React from "react";`enter code here`
import "./styles.css";
import { BrowserRouter as Router, Link, Route, Switch } from 'react-router-dom'
import ChildComponent from './ChildComponent'
export default function App() {
const someData = {
name : "Joh Doe"
}
return (
<div className="App">
<h1>This is parent Component</h1>
<Router>
<Link to='/secondpage'>Click me for Second Page</Link>
<Route
path='/secondpage'
render={(props) => (
<ChildComponent {...someData} isAuthed={true} />
)}
/>
</Router>
</div>
);
}
ChildComponent.js
import React from "react";
export default function ChildComponent(props) {
console.log("Data", props);
return <div>This is Second Page. It should open in new page. Also it should render incoming props</div>;
}
Work Demo
try doing this:
import React from 'react';
import {BrowserRouter as Router,Route, Redirect,Switch} from 'react-router-dom';
import Home from './App.js';
import Tutorials from './tutorials.js';
function Routes() {
return (
<Router>
<div>
<Switch>
<Route path="/" component = {Home}>
<Redirect from = "/blog/" to="/tutorials/" />
<Route path = "/tutorials/" component = {About} />
</Switch>
</div>
</Router>
)
}
i am change code .
parent component
import React from "react";
import { Link } from "react-router-dom";
export default function ParentComponent(props) {
console.log("Data", props);
return (
<div className="App">
<h1>This is parent Component</h1>
<Link to="/secondpage">Click me for Second Page</Link>
</div>
);
}
child component
import React from "react";
export default function ChildComponent(props) {
console.log("Data", props);
return (
<div>
This is Second Page. It should open in new page. Also it should render
incoming props
</div>
);
}
app component
import React from "react";
import "./styles.css";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import ChildComponent from "./ChildComponent";
import ParentComponent from "./parentComponent";
export default function App() {
const someData = {
name: "Joh Doe"
};
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/secondpage">
<ChildComponent {...someData} isAuthed={true} />
</Route>
<Route exact path="/" component={ParentComponent} />
</Switch>
</Router>
</div>
);
}
Work Demo

Cannot read property 'isLoggedIn' of null

Hi all I am currently stuck with the following:
Cannot read property 'isLoggedIn' of null
> 9 | const Header = () => {
10 | const {isLoggedIn} = useContext(AuthContext);
11 | return (
12 | <ul className="nav">
I am new in React and I was following a tutorial to implement a sign-in/sign-up form and sending data to firebase (which is also something completely new to me). I was able to fix a couple of previous issues on my own but I am now stuck at this one.
If I don't import the Header into the Routing the site works fine but as soon as I try to import it in any way to Routing.js it's failing.
Header.js
import React, { useContext } from "react";
import routes from "./routes";
import { Link } from "react-router-dom";
import { AuthContext } from "./test";
const Header = () => {
const {isLoggedIn} = useContext(AuthContext);
return (
<ul className="nav">
{routes.map((route, i) => (
<li key={i}>
<Link to={route.path}>{route.name}</Link>
</li>
))}
{isLoggedIn && <li><Link to="/reports">Profile</Link></li>}
</ul>
)
}
export default Header;
Routing.js
import React from "react";
import Head from "./Head";
import Join from "./Join";
import Login from "./Login";
import Test from "./test";
import HomePage from "./HomePage";
import Header from "./Header";
import { BrowserRouter as Router, Switch, Route, Link} from "react-router-dom";
function Home() {
return (
<div className="App">
<Head />
<HomePage />
</div>
);
}
function Reviews() {
return (
<div className="App">
<Head />
</div>
);
}
function Logging() {
return (
<div className="App">
<Head />
<Header />
<Test />
</div>
);
}
function Signup() {
return (
<div className="App">
<Head />
<Header />
<Test />
</div>
);
}
function App() {
return (
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/review" exact component={Reviews} />
<Route path="/login" exact component={Logging} />
<Route path="/signup" exact component={Signup} />
</Switch>
</Router>
)
}
export default App;
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { Switch, BrowserRouter as Router, Route } from "react-router-dom";
import routes from "./routes.js";
import Header from "./Header";
import "./styles.css";
import * as firebase from "firebase";
import firebaseConfig from "./firebase.config";
import protectedRoutes from './protectedRoutes'
import ProtectedRouteHoc from './ProtectedRouteHoc'
firebase.initializeApp(firebaseConfig);
export const AuthContext = React.createContext(null);
function Test() {
const [isLoggedIn, setLoggedIn] = useState(false);
function readSession() {
const user = window.sessionStorage.getItem(
`firebase:authUser:${firebaseConfig.apiKey}:[DEFAULT]`
);
if (user) setLoggedIn(true)
}
useEffect(() => {
readSession()
}, [])
return (
<AuthContext.Provider value={{ isLoggedIn, setLoggedIn }}>
Is logged in? {JSON.stringify(isLoggedIn)}
<div className="App">
<Router>
<Header isLoggedIn={isLoggedIn}/>
<Switch>
{protectedRoutes.map(route => (
<ProtectedRouteHoc
key={route.path}
isLoggedIn={isLoggedIn}
path={route.path}
component={route.main}
exact={route.exact}
public={route.public}
/>
))}
{routes.map(route => (
<Route
key={route.path}
path={route.path}
exact={route.exact}
component={route.main}
/>
))}
</Switch>
</Router>
</div>
</AuthContext.Provider>
);
}
export default Test;
I would appreciate any tips or things I can read through to get a better understanding in this.
You're destructing the return value of useContext(AuthContext). You're expecting it to return an object with a key isLoggedIn, e.g. { isLoggedIn: false }, but it's returning null instead. You probably haven't given it a default value when you instantiated the context instance, e.g.
// Possibly what you're doing, no default value
const AuthContext = React.createContext() // null
// Instantiated with a default value
const AuthContext = React.createContext({ isLoggedIn: false })

React routes dosen't show my components. Only one component is shown, others are not

I have components that I want show in my app. But only my "Header.js" component is shown at "App.js"
react-router-dom is installed, when i npm start my app is open but only header is shown. Can someone please help? I am not sure what I'm missing here?
My App.js
import React, { Component } from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Header from './components/Header.js';
import VehicleMake from './components/VehicleMake.js';
import VehicleModel from './components/VehicleModel.js';
import VehicleDetails from './components/VehicleDetails.js';
import AddNewVehicle from './components/AddNewVehicle.js';
import './App.css';
class App extends Component {
render(){
return (
<div className="App">
<Router>
<Header text="Vehicle by Ivan Radunković"/>
<Route exact path="/makes/:vehicleMake" component={VehicleMake} />
<Route exact path="/models/:vehicleModel" component={VehicleModel}/>
<Route exact path="/vehicle/:vehicleId" component={VehicleDetails}/>
<Route exact path="/add" component={AddNewVehicle} />
</Router>
</div>
)
}
}
export default App;
Header.js that is shown correct
import '../App.css'
import React, { Component } from 'react';
class Header extends Component {
render(){
return(
<header className="header">
<div className="headerText">
<h1>{this.props.text}</h1>
</div>
<img src="https://s.aolcdn.com/dims-global/dims3/GLOB/legacy_thumbnail/788x525/quality/85/https://s.aolcdn.com/commerce/autodata/images/USC90MBC891A021001.jpg" alt="header" className="headerImage"/>
</header>
)
}
}
export default Header;
And one component that I don't see.
VehicleMake.js
import React from 'react';
import { inject, observer } from 'mobx-react';
import { Link } from 'react-router-dom';
const VehicleMake = ({ VehicleStore, match, location, props}) => {
const {
params: { vehicleMake }
} = match
return (
<>
<Link to="/"><button className="button backButton">Back</button></Link>
<h3 className="title">Makes</h3>
<div className="vehiclesDiv">
{VehicleStore.filteredVehicles.filter(vehicle => vehicle !== null && vehicle.VehicleMake === vehicleMake).map((vehicle) => (
<div key={vehicle.id} className="vehicle">
<img src={vehicle.image} alt="" className="listImage"/>
<Link to={`/makes/${vehicle.VehicleMake}`} style={{ textDecoration: 'none' }}><h3 className="vehicleTitle">{vehicle.VehicleMake}</h3></Link>
<Link to={`/models/${vehicle.VehicleModel}`} style={{ textDecoration: 'none' }}><h4 className="vehicleSubtitle">{vehicle.VehicleModel}</h4></Link>
<Link to={`/vehicle/${vehicle.id}`} style={{ textDecoration: 'none' }}><h4 className="vehicleTitle">Details</h4></Link>
</div>
))}
</div>
</>
)
}
export default inject ('VehicleStore') (observer(VehicleMake))
Move <Header.. outside of <Router>
<Header text="Vehicle by Ivan Radunković"/>
<Router>
<Route exact path="/makes/:vehicleMake" component={VehicleMake} />
...

React Router changes Link but doesnt render proper component

Hello I'm working with React Router... I have two components App.js and SideNavComponent. I want to click the link in the SideNavComponent to and travel to the correct Component.
Right now when I click on the Link it changes the URL but does not render the correct component. However if I change the URL myself the correct view renders.
App.js
import React, { Component } from 'react';
import { Col, Well, Panel } from 'react-bootstrap';
import NavbarComponent from './NavbarComponent';
import SideNavComponent from './SideNavComponent';
import Router from './Router';
class App extends Component {
render() {
return (
<div>
<div className="header">
<NavbarComponent />
</div>
<div className="body">
<Col md={3}>
<Well>
<SideNavComponent />
</Well>
</Col>
<Col md={9}>
<Panel>
<Router />
</Panel>
</Col>
</div>
<div className="footer" />
</div>
);
}
}
export default App;
SideNavComponent
import React, { Component } from 'react';
import { Nav, NavItem } from 'react-bootstrap';
import { Link, BrowserRouter, Switch } from 'react-router-dom';
class SideNavComponent extends Component {
state = {
selectedLink: 1
};
selectLink(key) {
this.setState({ selectedLink: key });
}
render() {
return (
<BrowserRouter>
<div style={{ flexDirection: 'column' }}>
<Link to="/">Home</Link>
<Link to="/device">Device</Link>
<Link to="/transform">Transformation</Link>
<Link to="/graph">Graphs</Link>
</div>
</BrowserRouter>
);
}
}
export default SideNavComponent;
Router.js
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import HomeComponent from './pages/HomeComponent';
import DeviceComponent from './pages/DeviceComponent';
import TransformationComponent from './pages/TransformationComponent';
import GraphComponent from './pages/GraphComponent';
const Router = () => {
return (
<BrowserRouter>
<div>
<Switch>
<Route path="/device" component={DeviceComponent} />
<Route path="/transform" component={TransformationComponent} />
<Route path="/graph" component={GraphComponent} />
<Route exact path="/" component={HomeComponent} />
</Switch>
</div>
</BrowserRouter>
);
};
export default Router;
The problem is you have multiple instances of browser router and history is getting confused. You can fix this by re-organising the structure of application like the below example.
// *-----------------------*
// | MAIN-APP COMPONENT |
// *-----------------------*
import React, { Component } from "react";
import { Col, Well, Panel } from "react-bootstrap";
import { Route, Switch } from "react-router-dom";
import SideNavComponent from "./SideNavComponent";
const HomeComponent = () => <div>Home</div>;
const GraphComponent = () => <div>Graph</div>;
const DeviceComponent = () => <div>Device</div>;
const TransformationComponent = () => <div>Transformation</div>;
class App extends Component {
render() {
return (
<div>
<div className="header" />
<div className="body">
<Col md={3}>
<Well>
<SideNavComponent />
</Well>
</Col>
<Col md={9}>
<Panel>
<Switch>
<Route path="/device" component={DeviceComponent} />
<Route path="/transform" component={TransformationComponent} />
<Route path="/graph" component={GraphComponent} />
<Route exact path="/" component={HomeComponent} />
</Switch>
</Panel>
</Col>
</div>
<div className="footer" />
</div>
);
}
}
export default App;
// *-----------------------*
// | SIDENAV-COMPONENT |
// *-----------------------*
import React, { Component } from "react";
import { Nav, NavItem } from "react-bootstrap";
import { Link } from "react-router-dom";
class SideNavComponent extends Component {
render() {
return (
<div style={{ flexDirection: "column" }}>
<Link to="/">Home</Link>
<Link to="/graph">Graphs</Link>
</div>
);
}
}
export default SideNavComponent;
// *-----------------------*
// | MAIN.JS (ENTRY POINT) |
// *-----------------------*
import React from 'react'
import { render } from 'react-dom'
import App from './components/App';
import { BrowserRouter } from 'react-router-dom';
render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'));

React-router route won't trigger

First, i am sorry if this problem has been asked before. I am currently new to react-router, i don't know what to ask. So, i am trying to make a sidebar component in my apps, this sidebar composed of material-ui drawer, listItems. Each listItem has a link i put as its containerElement attribute value. Selecting each list does change the url, but component that each route should display won't show.
Here is my code:
App.js
import React, { Component } from 'react'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import Sidebar from './components/Sidebar'
import {
BrowserRouter as Router,
Route,
} from 'react-router-dom'
var injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();
const ListItem = () => (
<div>
<h2>List Item</h2>
</div>
)
const CreateForm = () => (
<div>
<h2>Create Form</h2>
</div>
)
const SearchItem = () => (
<div>
<h2>Search Item</h2>
</div>
)
class App extends Component {
render() {
return (
<MuiThemeProvider>
<Router>
<div>
<Sidebar />
<Route exact path="/" component={ListItem}/>
<Route path="/create" component={CreateForm}/>
<Route path="/search" component={SearchItem}/>
</div>
</Router>
</MuiThemeProvider>
)
}
}
export default App;
Sidebar.js
import React, {Component} from 'react'
import Drawer from 'material-ui/Drawer'
import {List, ListItem, makeSelectable} from 'material-ui/List'
import Subheader from 'material-ui/Subheader'
import {Link} from 'react-router-dom'
let SelectableList = makeSelectable(List)
function wrapState(ComposedComponent) {
return class SelectableList extends Component {
componentWillMount() {
this.setState({
selectedIndex: this.props.defaultValue,
})
}
handleRequestChange = (event, index) => {
this.setState({
selectedIndex: index,
})
}
render() {
return (
<ComposedComponent
value={this.state.selectedIndex}
onChange={this.handleRequestChange}
>
{this.props.children}
</ComposedComponent>
)
}
}
}
SelectableList = wrapState(SelectableList)
const ListSelectable = () => (
<SelectableList defaultValue={1}>
<Subheader>Basic CRUD operation</Subheader>
<ListItem
value={1}
primaryText="List"
containerElement={<Link to='/'/>}
/>
<ListItem
value={2}
primaryText="Create"
containerElement={<Link to='/create'/>}
/>
<ListItem
value={3}
primaryText="Search"
containerElement={<Link to='/search'/>}
/>
</SelectableList>
);
class Sidebar extends Component {
render() {
return (
<Drawer>
<ListSelectable />
</Drawer>
)
}
}
export default Sidebar
Note: The selectable list implementation i copied from material-ui docs.
Your component is covered by the sidebar. Try to put some margin on the left.
import React, { Component } from 'react'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import Sidebar from './components/Sidebar'
import {
BrowserRouter as Router,
Route,
} from 'react-router-dom'
var injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();
const ListItem = () => (
<div>
<h2 style={{marginLeft:'300'}}>List Item</h2>
</div>
)
const CreateForm = () => (
<div>
<h2 style={{marginLeft:'300'}}>Create Form</h2>
</div>
)
const SearchItem = () => (
<div>
<h2 style={{marginLeft:'300'}}>Search Item</h2>
</div>
)
class App extends Component {
render() {
return (
<MuiThemeProvider>
<Router>
<div>
<Sidebar />
<Route exact path="/" component={ListItem}/>
<Route path="/create" component={CreateForm}/>
<Route path="/search" component={SearchItem}/>
</div>
</Router>
</MuiThemeProvider>
)
}
}
export default App;

Resources