How to use Header Footer in Reactjs - javascript

I am new in Reactjs(Nextjs), I want to create file "header" and "footer" so i can use this file in all pages,So i want to know how can i do this and which is better option
Should i create "Layout.js" and then call Header in this file
Or should i use "Header" and "footer" in _app.js (without create layout file)
Here is my layout.js
import React, { Component } from 'react';
import Header from './Header';
class Layout extends Component {
render () {
const { children } = this.props
return (
<div className='layout'>
<Header />
{children}
</div>
);
}
}
or there is any other way,How can i do this,Thank you in advance.

Please refer this documentation for basic layout feature in NextJs
First create Layout component
import Header from './header'
import Footer from './footer'
export default function Layout({ children }) {
return (
<>
<Header/>
<main>{children}</main>
<Footer />
</>
)
}
Import and use the <Layout> component in the entry file,
// pages/_app.js
import Layout from '../components/layout'
export default function MyApp({ Component, pageProps }) {
return (
<Layout>
{/* All your page components */}
</Layout>
)
}
This will wrap your page components in the Header and Footer included in the Layout.

First create your Header & Footer then if you are using React.js go to App and put header and footer there like below:
const App = () => {
return (
<>
<Header />
// your routes go here
<Footer />
</>
)
}
For Next.js go to _app.tsx/jsx the entry point of all your pages
export default function MyApp({ Component, pageProps }) {
return (
<>
<Header />
<Component {...pageProps} />
<Footer />
</>
);
}
if you want to make different layouts or isolate that layout in a separate component you can do so.

Related

Unable to hide some components from some specific routes

So I have this app which have the same layout in all routes except in two, Login and Register. I have been trying to have a totally separate layout for Login and Register routes but I'm unable to do so.
The App component have all the routes and I'm checking with conditionals the value of of the components which I want to hide with the help of window.location.pathnam. If the user is in '/' (which is the login route) or '/register', then return empty string. If they are in some other routes, then return those components.
But right now the login/register route doesn't show the components but if I go to an inner route where there were supposed to be header, sidebar, footer components, I don't see them. They disappeared from the routes where they are supposed to be.
What am I doing wrong here?
Here's the App comp:
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Header from './components/Header/Header';
import Sidebar from './components/Sidebar/Sidebar';
import Footer from './components/Footer/Footer';
import style from './App.module.css';
import RegisterScreen from './screens/RegisterScreen/RegisterScreen';
import LoginScreen from './screens/LoginScreen/LoginScreen';
import Screen3 from './screens/Screen3/Screen3';
import Screen4 from './screens/Screen4/Screen4';
import Screen5 from './screens/Screen5/Screen5';
import Screen6 from './screens/Screen6/Screen6';
const App = () => {
let header = window.location.pathname === '/' || '/register' ? '' : <Header />;
let sidebar = window.location.pathname === '/' || '/register' ? '' : <Sidebar />;
let footer = window.location.pathname === '/' || '/register' ? '' : <Footer />;
return (
<Router>
{/* <Header /> */}
{header}
<div className={style.appBody}>
{/* <Sidebar /> */}
{sidebar}
<main className={style.main}>
<Switch>
<Route path='/' component={LoginScreen} exact />
<Route path='/register' component={RegisterScreen} exact />
<Route path='/screen3' component={Screen3} exact />
<Route path='/screen4' component={Screen4} exact />
<Route path='/screen5' component={Screen5} exact />
<Route path='/screen6' component={Screen6} exact />
</Switch>
</main>
</div>
{/* <Footer /> */}
{footer}
</Router>
)
}
export default App;
Use useLocation from react-router-dom to get the current pathname.
With the .split() function you're able to get the last item.
In the components that change depending on the location (Header, Footer, ...), create your condition (using ternary operator or switch case condition).
Examples :
Header.js (with ternary operator)
import React from 'react';
import { useLocation } from 'react-router-dom';
export default function Header() {
const path = useLocation().pathname;
const location = path.split('/')[1];
return (
<div>
{location === 'login' ? (
<div>
</div>
) : (
<div>
</div>
)}
</div>
);
}
Footer.js (with switch case condition)
import React from 'react';
import { useLocation } from 'react-router-dom';
import ComponentA from './components/ComponentA';
import ComponentB from './components/ComponentB';
import ComponentC from './components/ComponentC';
export default function Footer() {
const path = useLocation().pathname;
const location = path.split('/')[1];
const checkLocation = (uri) => {
switch (uri) {
case 'login':
return <ComponentA />;
case 'register':
return <ComponentB/>;
case 'about':
return <ComponentC />;
default:
return null;
}
};
return (
<div>
{checkLocation(location)}
</div>
);
}
Demo: Stackblitz
Create two different layout , my suggestion is create src/layouts folder and save here your layouts. On your app.js or index.js use react router two switch between different layouts
Ps. Basically your sidebar, footer, navbar should be inside of your customize layout not on app.js or index.js

Adding a persistent component to _app.js in Nextjs

So I am playing around with my first Nextjs app and am having trouble with adding a persistent sidebar.
I found Adam Wathan's article on persistent layouts in nextjs, but it seems like there is a newer pattern that was added recently using the _app.js page. I went to the docs and a few of the github issues around it, but it doesn't looks like there's a lot of documentation around it yet.
So for my example, I have my _app.js file:
import '../css/tailwind.css'
import Head from 'next/head'
import Sidebar from "../components/Sidebar";
export default function App({Component, pageProps}){
return(
<>
<Head />
<Component {...pageProps} />
</>
)
}
import React, { useState } from "react";
import Transition from "../components/Transition";
import Link from 'next/link'
function Sidebar({ children }) {
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const [hideSidebarMenu, setHideSidebarMenu] = useState(true);
const openSidebar = () => {
setIsSidebarOpen(true);
setHideSidebarMenu(false);
};
const closeSidebar = () => {
setIsSidebarOpen(false);
};
const hideSidebar = () => {
setHideSidebarMenu(true);
};
return(
<div>
/*sidebar links here*/
</div>
)
}
export default Sidebar;
How do I integrate my sidebar component into this? I've tried adding it next to component and wrapping component and a few other iterations with no luck. Hopefully I'm just missing something simple.
This is odd. I could have swore I tried this very simple solution before, but something like this was completely sufficient.
This solution will feed in the page that you are on using the children prop in the sidebar.
import '../css/tailwind.css'
import Head from 'next/head'
import Sidebar from "../components/Sidebar";
export default function App({Component, pageProps}){
return(
<>
<Head />
<Sidebar >
<Component {...pageProps} />
</Sidebar>
</>
)
}
this option will just render the sidebar along with the content
import '../css/tailwind.css'
import Head from 'next/head'
import Sidebar from "../components/Sidebar";
export default function App({Component, pageProps}){
return(
<>
<Head />
<Sidebar />
<Component {...pageProps} />
</>
)
}

React + Nextjs - External scripts loading but not executing together

I have a next js application and I need to integrate it with an existing site by importing the header and footer from the parent site. It the markup along with supporting libs are being delivered through a JS file, one for each header and footer respectively. This is how my _apps.js, navigation.js and footer.js file looks like:
_app.js:
render() {
return (
<Provider store={reduxStore}>
<Head headerData={newStaticData} />
<Navigation />
<OtherComponents />
<Footer />
</Provider>
);
}
navigation.js:
class Navigation extends Component {
shouldComponentUpdate() {
return false;
}
componentDidMount() {
const script = document.createElement('script');
script.src = "https://mainsite.com/external/header.js";
script.async = true
document.body.appendChild(script);
}
render() {
return (
<div id="target_div_id"></div>
)
}
}
export default Navigation;
footer.js:
class Footer extends Component {
shouldComponentUpdate() {
return false;
}
componentDidMount() {
const script = document.createElement('script');
script.src = "https://mainsite.com/external/footer.js";
script.async = true
document.body.appendChild(script);
}
render() {
return (
<div id="footer_target_id"></div>
)
}
}
export default Footer;
When I run this code, just the main navigation will appear but not the footer. If it comment out the navigation, then the footer will appear. I am not sure why but it looks like only one loads at a time. I have tried using script.defer=true but hasn't helped either.
Can anyone advice what might be causing this and what's the resolution?
TIA.
you can easily do this with react-helmet even in child component
import React from "react";
import {Helmet} from "react-helmet";
class Navigation extends Component {
render() {
return (
<div id="target_div_id">
<Helmet>
<script type="text/javascript" href="https://mainsite.com/external/header.js" />
</Helmet></div>
)
}
}
export default Navigation;
try you use react hooks instead of react Component lifecycle
const Navigation = ()=> {
return (
<div id="target_div_id">
<Helmet>
<script type="text/javascript" href="https://mainsite.com/external/header.js" />
</Helmet></div>
)
}
export {Navigation} ;
// parent
import {Navigation} from "../Navigation.js";
I would suggest you not to use _app.js for this.
Try creating a Layout file like below:
// MainLayout.js
import NavBar from './Navigation.js'
import Footer from './Footer.js'
export default ({ children }) => (
<>
<Navigation />
{children}
<Footer />
</>
)
And have your main file as like this:
// index.js
import React from 'react'
import MainLayout from '../components/Layouts/MainLayout.js'
import Banner from '../components/Banner/Banner.js'
export default function Home() {
return (
<>
<MainLayout>
<Banner />
</MainLayout>
</>
)
}

How to render a component according to the route using GatsbyJS?

I'm using GatsbyJS and I'm trying to render a different header according to the route of the URL.
Example :
mydomain.com/ => should render HeaderLanding
mydomain.com/blog => should render HeaderMain
Does anyone know the proper way to create a conditional rendering to display a component according to the route in the layout.js file?
Thank you for your support.
// layout.js
import React from "react"
import PropTypes from "prop-types"
import HeaderLanding from "./header-landing"
import HeaderMain from "./header-main"
import Footer from "./footer"
const Layout = ({ children }) => {
return (
<>
<Header/>
<div className="content-wrapper">
<main>{children}</main>
</div>
<Footer/>
</>
)
}
export default Layout
Pretty much what #ravibagul91 have answered, however Gatsby doesn't use react-router-dom.
If Layout is a page component, Gatsby will pass it a location prop. You can extract location.pathname & apply your logic there
const Layout = ({ children, location }) => {
const isMain = location.pathname === 'your-path'
return (
<>
{ isMain ? <HeaderMain> : <HeaderLanding> }
<div className="content-wrapper">
<main>{children}</main>
</div>
<Footer/>
</>
)
}
export default Layout
If Layout is not a page component, you can import the HOC Location from #reach/router:
import { Location } from '#reach/router' // gatsby's dep
const Layout = ({ children }) => {
return (
<Location>
{({ location }) => (
...
)}
</Location>
)
}
Or simply pass the location props from a Gatsby page component to this component from each page:
import Layout from '../components/layout'
export default ({ location }) => (
<Layout location={location}>
...
</Layout>
)
You can make use of location object of withRouter HOC.
import { withRouter } from 'react-router-dom';
const Layout = ({ children, location }) => {
return (
<>
{location.pathname.split('/')[1] ==="blog" ? <HeaderMain /> : <HeaderLanding /> }
<div className="content-wrapper">
<main>{children}</main>
</div>
<Footer/>
</>
)
}
export default withRouter(Layout)
Update
Gatsby v2 has switched routers from react-router with #reach/router
From the docs,
In v1, the layout component had access to history, location, and match props. In v2, only pages have access to these props. If you need these props in the layout component, pass them through from the page.
So your Layout component should be,
const Layout = ({ children, location }) => {
return (
<>
{location.pathname.split('/')[1] ==="blog" ? <HeaderMain /> : <HeaderLanding /> }
<div className="content-wrapper">
<main>{children}</main>
</div>
<Footer/>
</>
)
}
export default Layout
And your Page component should be, (just example)
import React from "react"
import Layout from "../components/layout"
export default props => (
<Layout location={props.location}> //Pass location here
<div>Hello World</div>
</Layout>
)
Or you can use Location.
Typically you only have access to the location in Route Components, Location provides the location anywhere in your app with a child render prop.
<Location>
{props => {
props.location
props.navigate
}}
</Location>
// usually folks use some destructuring
<Location>
{({ location })=> {
// ...
}}
</Location>

How properly setup react-router-dom in Home Route?

I have this index.js:
<Provider store={store}>
<Router history={history}>
<App/>
</Router>
</Provider>
this App.js:
<Switch>
<Route exact path="/" component={Home} />
<Route
path="/login"
render={() => <Login userError={this.state.userError} />}
/>
<Route path="/registration" component={Registration} />;
</Switch>
and Home.js:
<div className="Home">
<Header/>
<div className="content">
<Sidenav/>
<Switch>
<Route path="/friends" component={Friends}/>
</Switch>
<Feed/>
</div>
</div>
I want Friends component to be rendered inside content block, but now if I try to reach /friends route via Link I am getting blank page. If I set /friends Route in App.js, it will be OK, but I won't have it in my content class, because it will be another page.
May you give me a hand with that?
Also in feature I will be have more items to display in content, that's why I put Switch in Home.js
Thanks in advance!
Move your content class and <Friends>
The issue you're having is that the component Home is not rendering when you visit /friends because it will only render when you go to /
To fix this just move the Route into the App.js file, along with the content class into the Friends component.
To make this easier, you could make your content class into a component. This way you could wrap it around all of the stuff you render.
Or move <Friends> and wrap content
What I mean by this is that you could also create your own Route component that wraps whatever component passed to it in a Content component. It might look similar to this:
const ContentRoute = ({ component, ...props }) => (
<Route {...props} component={() => (
<Content>
<component />
</Content>
)}>
</Route>
)
You can access demo here
Here what I have done. This demonstrates how to set layout when page's changing.
- src/
-- components/
--- Header.js
--- Sidenav.js
-- pages/
--- Home.js
--- Login.js
--- withBase.js
-- App.js
-- BaseLayout.js
-- routes.js
At first, let's make dummy components.
components/Header
import React from 'react';
export default () => (
<div>
This is Header.
</div>
);
components/Sidenav
import React from 'react';
export default () => (
<div>
This is Sidenav.
</div>
);
Then, pages.
pages/Home
import React from 'react';
import { NavLink } from 'react-router-dom';
import withBase from './withBase';
const Home = () => (
<div>
<p>Welcome Home!!!</p>
<NavLink to="/login">Go to login page</NavLink>
</div>
);
export default withBase(Home);
pages/Login
import React from 'react';
import { NavLink } from 'react-router-dom';
import withBase from './withBase';
const Login = () => (
<div>
<p>You have to login here...</p>
<NavLink to="/">Go home</NavLink>
</div>
);
export default withBase(Login);
pages/withBase
import React from 'react';
export default WrappedComponent => (
class extends React.Component {
componentDidMount() {
this.props.showHeaderSidenav();
}
render() {
return <WrappedComponent />;
}
}
);
As you see, withBase is a HOC. It runs showHeaderSidenav when the page is mounted.
App
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import BaseLayout from './BaseLayout';
import routes from './routes';
export default class extends React.Component {
state = {
withHeaderSidenav: true
}
showHeaderSidenav = (withHeaderSidenav = true) => {
this.setState({ withHeaderSidenav });
}
render() {
return (
<BaseLayout withHeaderSidenav={this.state.withHeaderSidenav}>
<Switch>
{routes.map(route => (
<Route
exact
key={route.path}
path={route.path}
render={() => (
<route.component
showHeaderSidenav={() => this.showHeaderSidenav(route.withHeaderSidenav)}
/>
)}
/>
))}
</Switch>
</BaseLayout>
);
}
}
BaseLayout
import React from 'react';
import Header from './components/Header';
import Sidenav from './components/Sidenav';
export default ({ withHeaderSidenav, children }) => (
<div>
{withHeaderSidenav && <Header />}
<div className="content">
{withHeaderSidenav && <Sidenav />}
{children}
</div>
</div>
);
We can say that BaseLayout is like a wrapper. It contains dynamic components which will be shown based on withHeaderSidenav prop.
Finally...
routes
import Home from './pages/Home';
import Login from './pages/Login';
export default [
{
path: '/',
component: Home,
withHeaderSidenav: true
},
{
path: '/login',
component: Login,
withHeaderSidenav: false
},
];
You could have moved(declared) content component inside Friends component. I do not see the reason why content component should live outside of Friends component. You can declare content component inside any component that needs it.Content component does not have to mess with routing implementation

Categories