React Redux Connect wrap component - reactjs

Im learning react and the instructor creates components as in Code 1 where as I create the function as in Code 2. How do we wrap code 2 within Redux Connect()?
Code 1
const Header = ({ currentUser }) => (
<div className='header'>
<Link className='logo-container' to='/'>
<Logo className='logo' />
</Link>
</div>
);
const mapStateToProps = state => ({
currentUser: state.user.currentUser
});
export default connect(mapStateToProps)(Header);
Code 2
import React from 'react';
import {connect} from 'react-redux';
export default function Header({currentUser}) {
return (
<div className='header'>
<Link className='logo-container' to="/">
<Logo className='logo' />
</Link>
<div className='options'>
<Link className='option' to="/shop">
SHOP
</Link>
<Link className='option' to="/shop">
CONTACT
</Link>
{
currentUser ?
<div className='option' onClick={() => auth.signOut()}>SIGN OUT</div>
:
<Link className='option' to="/signin">SIGN IN</Link>
}
</div>
</div>
)
}

I believe this should work:
import React from 'react';
import {connect} from 'react-redux';
export default connect(mapStateToProps)(function({currentUser})) {
return (
<div className='header'>
<Link className='logo-container' to="/">
<Logo className='logo' />
</Link>
<div className='options'>
<Link className='option' to="/shop">
SHOP
</Link>
<Link className='option' to="/shop">
CONTACT
</Link>
{
currentUser ?
<div className='option' onClick={() => auth.signOut()}>SIGN OUT</div>
:
<Link className='option' to="/signin">SIGN IN</Link>
}
</div>
</div>
)
}
Then, you can import it at any file using this line:
import AnyNameYouWant from './Header.js';
If we would have exported it like this:
export const Header = connect(mapStateToProps)(function({currentUser})) {...
Then you would have needed to change your import statements to this:
import { Header } from './Header.js';
Hope it helps.

Related

encountered errors on following paths React / next.js

could somone help i'm stuck in such problem with next.js here is my code
this is the error i get in the console
Error: Export encountered errors on following paths:
/admin
/user
in pages in folder named admin/index.js
import Layout from "../../components/Layout";
import Admin from "../../components/auth/Admin";
import Link from "next/link";
const AdminIndex = () => {
return (
<Layout>
<Admin>
<div className="container-fluid">
<div className="row">
<div className="col-md-12 pt-5 pb-5">
<h2>Admin Dashboard</h2>
</div>
<div className="col-md-4">
<ul class="list-group">
<li className="list-group-item">
<Link href="/admin/crud/project">
<a>Create Project</a>
</Link>
</li>
</ul>
</div>
<div className="col-md-8">right</div>
</div>
</div>
</Admin>
</Layout>
);
};
export default AdminIndex;
in folder pages/user/index.js
Error: Export encountered errors on following paths:
/admin
/user
import Layout from "../../components/Layout";
import Private from "../../components/auth/Private";
import Link from "next/link";
const UserIndex = () => {
return (
<Layout>
<Private>
<div className="container-fluid">
<h2>User Dashboard</h2>
</div>
</Private>
</Layout>
);
};
export default UserIndex;
and finally this is my header
import React, { useState } from "react";
import Link from "next/link";
import Router from "next/router";
import nProgress from "nprogress";
import { APP_NAME } from "../config";
import { signout, isAuth } from "../actions/auth";
import {
Collapse,
Navbar,
NavbarToggler,
Nav,
NavItem,
NavLink,
} from "reactstrap";
Router.onRouteChangeStart = (url) => nProgress.start();
Router.onRouteChangeComplete = (url) => nProgress.done();
Router.onRouteChangeError = (url) => nProgress.done();
//next.js giving us the option to use such option
const Header = () => {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => {
setIsOpen(!isOpen);
};
return (
<div>
<Navbar color="light" light expand="md">
<Link href="/">
<NavLink className="font-weight-bold">{APP_NAME}</NavLink>
</Link>
<NavbarToggler onClick={toggle} />
<Collapse isOpen={isOpen} navbar>
<Nav className="ml-auto" navbar>
{!isAuth() && (
<React.Fragment>
<NavItem>
<Link href="/signin">
<NavLink>Signin</NavLink>
</Link>
</NavItem>
<NavItem>
<Link href="/signup">
<NavLink>Signup</NavLink>
</Link>
</NavItem>
</React.Fragment>
)}
{isAuth() && isAuth().role === 0 && (
<NavItem>
<Link href="/user">
<NavLink style={{ cursor: "pointer" }}>
{`${isAuth().name}'s Dashboard`}
</NavLink>
</Link>
</NavItem>
)}
{isAuth() && isAuth().role === 1 && (
<NavItem>
<Link href="/admin">
<NavLink style={{ cursor: "pointer" }}>{`${
isAuth().name
}'s Dashboard`}</NavLink>
</Link>
</NavItem>
)}
{isAuth() && (
<NavItem>
<NavLink
style={{ cursor: "pointer" }}
onClick={() => signout(() => Router.replace(`/signin`))}
>
Signout
</NavLink>
</NavItem>
)}
</Nav>
</Collapse>
</Navbar>
</div>
);
};
export default Header;

How to close sidenav when I click anywhere of the page in react js

**Nav-header.js**
The sidebar should not collapse when I am clicking outside of the page in react js. Please help with that. this is the code I wrote for the side menu. I am a beginner at the react js. Please help
import React, { useState } from 'react'
import * as FaIcons from 'react-icons/fa'
import * as AiIcons from 'react-icons/ai'
import { Link } from 'react-router-dom'
import { SidebarData } from './SidebarData'
import './Navbar.css'
import { IconContext } from 'react-icons'
const Header = () => {
const [sidebar, setsidebar] = useState(false)
const showSideBar = () => setsidebar(!sidebar)
return (
<>
<IconContext.Provider value={{ color: '#1D1D1D' }}>
<div className='navbar'>
<Link to="#" className='menu-bars'>
<FaIcons.FaBars onClick={showSideBar} color="#009540"/>
</Link>
<span className="meny">Meny</span>
</div>
<nav className={sidebar ? 'nav-menu active' : 'nav-menu' } >
<ul className='nav-menu-items' onClick={showSideBar}>
<li className='navbar-toggle'>
<Link to="#" className='menu-bars-logo'>
<AiIcons.AiOutlineClose/>
</Link>
</li>
{SidebarData.map((item, index) => {
return (
<li key={index} className={item.cName}>
<Link to={item.path}>
<span>{item.title}</span>
</Link>
</li>
)
})}
</ul>
</nav>
</IconContext.Provider>
</>
)
}
export default Header
You can use onblur, in react it would look like
return (
<div onBlur={() => {
... do something like setState
}}>
)

GatsbyJS: Change menu link when switching between pages

I have a simple Gatsby site using two languages. In the header component, there is a link to the second language, when clicking on it, that language becomes the selected one and the other must appear as an option. Everything works but does not load these changes without refreshing the page. What am I doing wrong? Here is my code:
import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"
import AnchorLink from "react-anchor-link-smooth-scroll"
import Logo from "../images/logo.svg"
const path = window.location.pathname;
const Header = ({ siteTitle }) => {
return (
<>
<header>
<div className="container">
<div className="nav-links">
<Link to="/" className="logo">
<Logo />
</Link>
<div className="wrapper">
<AnchorLink href="#contact" className="nav-item contact">
Contact us
</AnchorLink>
</div>
<AnchorLink className="button button--sm" href="#contact">
Contact
</AnchorLink>
{path === '/' && (
<Link to='/de' className="nav-item">
DE
</Link>
)}
{path === '/de' && (
<Link to='/' className="nav-item">
EN
</Link>
)}
</div>
</div>
</header>
</>
)
}
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: ``,
}
export default Header
I believe you should put the path variable inside the Header component so that it is re-evaluated on each render.
const Header = ({ siteTitle }) => {
const path = window.location.pathname;
return (
<>
<header>

How to show/hide menu items in next.js if user authenticated

I want to for example only show the logout button if a user is actually logged in.
My _app.js file:
import React from "react";
import App from "next/app";
import Navbar from "../components/navbar";
import Layout from "../components/layouts/mainLayout";
import { handleAuthSSR } from "../utils/auth";
export default class MyApp extends App {
render() {
const { Component, pageProps, userAuth } = this.props;
return (
<Layout userAuth={pageProps.token}>
<Component {...pageProps} />
</Layout>
);
}
}
Main Layout:
import Head from "next/head";
import Navbar from "../navbar";
const Layout = props => {
return (
<>
<Head>
<title>My App</title>
<link
rel="stylesheet"
href="https://bootswatch.com/4/cerulean/bootstrap.min.css"
></link>
<link href="/static/css/styles.css" rel="stylesheet"></link>
</Head>
<Navbar />
<div className="container">{props.children}</div>
</>
);
};
export default Layout;
Navbar:
import Link from "next/link";
import { logout } from "../utils/auth";
const Navbar = props => (
<nav className="navbar navbar-expand navbar-dark bg-dark mb-4">
<div className="container">
<a className="navbar-brand" href="#">
My App
</a>
<div className="collapse navbar-collapse">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link href="/">
<a className="nav-link">Home</a>
</Link>
</li>
<li className="nav-item">
<Link href="/about">
<a className="nav-link">About</a>
</Link>
</li>
<li className="nav-item">
<Link href="/register">
<a className="nav-link">Register</a>
</Link>
</li>
{props.userAuth ? (
<li>
<button className="btn btn-primary" onClick={logout}>
Logout
</button>
</li>
) : (
<li className="nav-item">
<Link href="/login">
<a className="nav-link">Login</a>
</Link>
</li>
)}
</ul>
</div>
</div>
</nav>
);
export default Navbar;
So, I am passing userAuth via props but I haven't actually got the logic for userAuth.
The handleAuthSSR looks like:
export const handleAuthSSR = ctx => {
const { token } = nextCookie(ctx);
if (ctx.req && !token) {
ctx.res.writeHead(302, { Location: "/login" });
ctx.res.end();
return;
}
if (!token) {
console.log("no token found");
Router.push("/login");
}
return token;
};
I am using this as part of a HOC when a user navigates around and it works but not sure how to get this to work with regards to the navigation show/hide.
I can see that you didn't pass the userAuth prop to the navbar component in mainLayout.js. Also you need to work on your Parent/Children props communications.
Maybe you can use your HOC to return token or false (or null instead of false). Use it then in navbar.js to toggle Login/Logout link.

shouldComponentUpdate() returns true but NavLink still doesn't work

I recently tried implementing a navlink like so:
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import '../css/navbar.css';
import logoWhite from '../../common/images';
const Navbar = props => {
return (
<div id="navbar" className="grid">
<Link to="/" className="column logo-container">
<img src={logoWhite} alt="Test logo" />
</Link>
<ul className="column navigation">
<li>
<NavLink to="/" exact className="nav-link" activeClassName="active">Home</NavLink>
</li>
<li>
<NavLink to="/match" className="nav-link" activeClassName="active">Partner Proposals</NavLink>
</li>
</ul>
</div>
);
};
export default Navbar;
Upon running I encountered the issue of the classname not being passed to the navlink when the route changed. Reading on articles and it led me to suspect that the shouldComponentUpdate method was being rendered false. So, I rewrote the Navbar like so:
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import '../css/navbar.css';
import logoWhite from '../../common/images';
class Navbar extends React.Component {
shouldComponentUpdate() {
console.log('Console log activated');
return true;
}
render() {
return (
<div id="navbar" className="grid">
<Link to="/" className="column logo-container">
<img src={logoWhite} alt="Test image" />
</Link>
<ul className="column navigation">
<li>
<NavLink to="/" exact activeClassName="active" className="nav-link">Home</NavLink>
</li>
<li>
<NavLink to="/match" activeClassName="active" className="nav-link">Partner Proposals</NavLink>
</li>
</ul>
</div>
);
}
}
export default Navbar;
What's strange is that the componentDidUpdate returned the value in the console (suggesting that it returned true), but the NavLink was still not passing the activeClassName
Can anyone suggest a solution to this problem?
Based on the suggestion from #mindaJalaj, I passed a pathname prop (which was rendering and re-rendering whenever there was a update to the route from the parent component), and I implemented the Navbar as follows
import React from 'react';
import PropTypes from 'prop-types';
import { Link, NavLink } from 'react-router-dom';
import { Icon } from 'semantic-ui-react';
import '../css/navbar.css';
import logo from '../../common/images/logo.png';
import navLinks from '../navLinks';
const Navbar = props => {
function renderNavLinks() {
return navLinks.map((navLink, index) => {
const key: string = `nav-link-${navLink.path}-${index}`;
const exact: boolean = navLink.exact || false;
return (
<li key={key}>
<NavLink
to={navLink.path}
exact={exact}
className="nav-link"
isActive={() => navLink.path === props.pathname}
activeClassName="active"
>
<Icon name={navLink.icon} />
<span>{navLink.title}</span>
</NavLink>
</li>
);
});
}
return (
<div id="navbar" className="grid">
<Link to="/" className="column logo-container">
<img src={logo} alt="Test logo" />
</Link>
<ul className="column navigation">{renderNavLinks()}</ul>
</div>
);
};
Navbar.propTypes = {
pathname: PropTypes.string
};
Navbar.defaultProps = {
pathname: '/'
};
export default Navbar;

Resources