How to get authetication status in react js component? - javascript

Below is the code of the react component of my project. this.props.isAuthenticatedis working when I return the component but when I print this.props.isAuthenticated inside componentDidMount I am getting false(print logout). How do I get authentication status true or false in react component?
I have added redux already and login logout working fine.
import React, { Component } from "react";
import { NavLink, Route, withRouter } from "react-router-dom";
import NewsListView from "../Container/NewsListView";
import StatsView from "../Container/StatsView";
import VotingView from "../Container/VotingView.js";
import Rightsidebar from "../Container/rightsidebar";
import Footer from "./footer";
import Loginform from "../Container/loginform";
import SignUp from "../Container/SignUp";
import { connect } from "react-redux";
import * as actions from "../Store/actions/auth";
class Header extends React.Component {
componentDidMount() {
{
this.props.isAuthenticated ? console.log("login") : console.log("logout");
}
}
render() {
return (
<div>
<nav className="navbar navbar-inverse">
<div className="container-fluid">
<div className="navbar-header">
<button
type="button"
className="navbar-toggle"
data-toggle="collapse"
data-target="#myNavbar"
>
<span className="icon-bar" />
<span className="icon-bar" />
<span className="icon-bar" />
</button>
<NavLink className="navbar-brand" to="/">
Save4thPillar
</NavLink>
</div>
<div className="collapse navbar-collapse" id="myNavbar">
<ul className="nav navbar-nav">
<li>
<NavLink to="/" className="navlink">
Home
</NavLink>
</li>
<li>
<NavLink to="/news" className="navlink">
news
</NavLink>
</li>
<li>
<NavLink to="/stats" className="navlink">
stats
</NavLink>
</li>
{this.props.isAuthenticated ? (
<li>
<NavLink
to="/logout"
onClick={this.props.logout}
className="navlink"
>
Logout
</NavLink>
</li>
) : (
<li>
<NavLink to="/login" className="navlink">
Login
</NavLink>
</li>
)}
</ul>
</div>
</div>
</nav>
<div className="container">
<div className="row">
<div className="col-md-8">
<Route exact path="/" component={VotingView} {...this.props} />
<Route exact path="/news" component={NewsListView} />
<Route exact path="/stats" component={StatsView} />
<Route exact path="/login" component={Loginform} />
<Route exact path="/signup" component={SignUp} />
</div>
<div className="col-md-4">
<Rightsidebar />
</div>
<div />
</div>
<Footer />
</div>
</div>
);
}
}
const mapDispatchToProps = dispatch => {
return {
logout: () => dispatch(actions.logout())
};
};
export default withRouter(
connect(
null,
mapDispatchToProps
)(Header)
);

You should implement the Header component's constructor. to use props in lifecycles
class Header extends React.Component {
componentDidMount() {
{
this.props.isAuthenticated ? console.log("login") : console.log("logout");
}
constructor(props){
super(props);
}
[...]
}

Related

I've just started learning React and got stuck at this error

Uncaught TypeError: Cannot read properties of undefined (reading 'pathname')
I have searched about this problem a lot and everywhere I'm getting answer to use to instead of href but I'm already using to
Here is my Code
app.js
import {
BrowserRouter,
Routes,
Route,
Link
} from "react-router-dom";
return (
<>
<Navbar
title="Texter"
aboutus="AboutTextUtils"
toggleMode={toggleMode}
mode={mode}
></Navbar>
<BrowserRouter>
<Routes>
<Route path="/about" element={<About />} />
<Route
path="/"
element= {<Text title="Enter the text below" mode={mode}/>}
/>
</Routes>
</BrowserRouter>
</>
This is navbar where the link tag is
import { Link, Router } from 'react-router-dom';
export default function Navbar(props) {
return (
<Router>
<nav className={`navbar navbar-expand-lg navbar-${props.mode} bg-${props.mode}`}>
<div className="container-fluid">
<a className="navbar-brand" href="/">{props.title}</a>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className="nav-item">
<Link className="nav-link active" aria-current="page" to={"/"}>Home</Link> //This is the Link tag
</li>
<li className="nav-item">
<Link className="nav-link" to={"/about"}>{props.aboutus}</Link> //This is the Link tag
</li>
</ul>
<div className={`form-check form-switch text-${props.mode === 'light'?'dark':'light'}`}>
<input className="form-check-input" onClick={props.toggleMode} type="checkbox" role="switch" id="flexSwitchCheckDefault"/>
<label className="form-check-label" htmlFor="flexSwitchCheckDefault">Enable Dark Mode</label>
</div>
</div>
</div>
</nav>
</Router>
)
Issue
You are rendering the Navbar component outside the BrowserRouter and then rendering the Navbar UI into the low-level Router component which has some required props.
See Router
declare function Router(
props: RouterProps
): React.ReactElement | null;
interface RouterProps {
basename?: string;
children?: React.ReactNode;
location: Partial<Location> | string; // <-- required!!
navigationType?: NavigationType;
navigator: Navigator; // <-- required!!
static?: boolean;
}
It's the location being undefined that can't access any pathname property.
Solution
Move the Navbar component into the BrowserRouter so there is a provided router context. Remove the Router in Navbar.
import { Link } from 'react-router-dom';
export default function Navbar(props) {
return (
<nav className={`navbar navbar-expand-lg navbar-${props.mode} bg-${props.mode}`}>
...
</nav>
);
}
import {
BrowserRouter,
Routes,
Route,
Link
} from "react-router-dom";
...
return (
<>
<BrowserRouter>
<Navbar
title="Texter"
aboutus="AboutTextUtils"
toggleMode={toggleMode}
mode={mode}
/>
<Routes>
<Route path="/about" element={<About />} />
<Route
path="/"
element={<Text title="Enter the text below" mode={mode} />}
/>
</Routes>
</BrowserRouter>
</>
);

React Router not rendering anything

when using react-router-dom, I cannot render any of my components or anything.
All it does is show a white screen, it doesn't add anything to my index.html template.
There aren't any errors however it says that in index.js there are unused variables that are my components.
Heres my code:
index.js
// Imports
import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.css';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { navbar, footer, home } from './components';
ReactDOM.render(
<Router>
<navBar />
<Routes>
<Route path="/" element={<home />} />
</Routes>
<footer />
</Router>,
document.getElementById("root")
);
home.jsx
import React from "react";
function home(){
return(
<div className="home">
<div class="container">
<div class="row allign-items-center my-5">
<div class="col-lg-7">
<img class="img-fluid rounded mb-4 mb-lg-0" src="./img/pizza.jpg" alt=""/>
</div>
<div class="col-lg-5">
<h1 class="font-weight-light">cencored</h1>
<p>cencored</p>
</div>
</div>
</div>
</div>
)
}
export default home;
navBar.jsx
import React from 'react';
import {NavLink} from 'react-router-dom';
function navBar(){
return(
<div className="navBar">
<nav className="navbar navbar-expand navbar-dar bg-dark">
<div className="container">
<NavLink className="navbar-brand" to="/"><img src="../img/logo.png" alt="logo" style="width:500px;height:500px;"/></NavLink>
<div>
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<NavLink className="nav-link" to="/menu">Menu</NavLink></li>
<li className="nav-item">
<NavLink className="nav-link" to="/about">About</NavLink></li>
<li className="nav-item">
<NavLink className="nav-link" to="/contact">Contact</NavLink></li>
</ul>
</div>
</div>
</nav>
</div>
);
}
export default navBar;
footer.jsx
import React from 'react';
import {NavLink} from 'react-router-dom';
function footer(){
return(
<div className="footer">
<footer class="py-5 bg-dark fixed-bottom">
<div class="container">
<p class="m-0 text-center text-white">cencored</p>
</div>
<div>
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<NavLink className="nav-link" to="/">Home</NavLink></li>
<li className="nav-item">
<NavLink className="nav-link" to="/menu">Menu</NavLink></li>
<li className="nav-item">
<NavLink className="nav-link" to="/about">About</NavLink></li>
<li className="nav-item">
<NavLink className="nav-link" to="/contact">Contact</NavLink></li>
</ul>
</div>
</footer>
</div>
);
}
export default footer;
index.js (component exports)
export { default as navbar } from './navBar';
export { default as footer } from './footer';
export { default as home } from './home';
Instead of using the element prop on your Route try to component prop like
<Route path="/" component={Home}>
You also must capitalize components.
React components should use PascalCase names.
export { default as Navbar } from './navBar';
export { default as Footer } from './footer';
export { default as Home } from './home';
...
import { Navbar, Footer, Home } from './components';
ReactDOM.render(
<Router>
<NavBar />
<Routes>
<Route path="/" element={<Home />} />
</Routes>
<Footer />
</Router>,
document.getElementById("root")
);
You are missing import of Switch from 'react-router-dom' and after you have to wrap your Routes into . And into Routes you have to add all of your components with path not only Home component.
Pseudo code:
import { Switch, Route, Router } from "react-router-dom";
import Home from '.....path'
//import all routing componets
const Routes = () => {
return(
<Switch>
<Route exact path='/' component={Home}>
<Route exact path='/comp1' component={Comp1}>
<Route exact path='/comp2' component={Comp2}>
</Switch>)}
const App = () => {
<Router>
<GlobalNav />
<Container fluid={true}>
<SideNav />
<Routes />
</Container>
</Router>}
Then you can add your navbar anywhere but has to be wrapped into router. I just added as example i can have a typo somewhere but if you follow the concept it should work. And change your components to Pascal naming.

ReactJs Router changes url but not the page

I am building a portfolio website and am using react BrowserRouter, Link and Switch to manage my websites routing My problem is that when I click on the 'Projects' link it changes on url but not in view, however when I refresh the page it works.
here is what my routing currently looks like in my App.js.
import React, { Component } from 'react';
import NavBar from './Components/NavBar/NavBar'
import Home from './Components/Home/Home';
import Projects from './Components/Projects/Projects';
import { BrowserRouter ,Switch, Route, } from 'react-router-dom';
class App extends Component {
render() {
return (
<div className="App">
<NavBar />
<BrowserRouter>
<Switch>
<Route path="/" component={Home} exact={true} />
<Route path="/projects" component={Projects} />
</Switch>
</BrowserRouter>
</div>
);
}
}
export default App;
and this is what my Navbar.js looks like..
import React, {useState} from 'react';
import { NavLink, BrowserRouter } from 'react-router-dom'
import { Link } from 'react-scroll';
function NavBar() {
const [navbar,setNavbar] = useState(false)
const changeBackground = () => {
if(window.scrollY >= 100) {
setNavbar(true)
} else {
setNavbar(false)
}
}
window.addEventListener('scroll', changeBackground)
return(
<BrowserRouter>
<ul className="nav bg-white sticky-top nav-tabs nav-justified">
<li className="nav-item">
<Link
className={navbar ? "nav-link text-dark home" : "nav-link text-secondary home"}
to="home"
href="/"
smooth={true}
offset={50}
duration={500}>
Home
</Link>
</li>
<li className="nav-item">
<Link
className={navbar ? "nav-link text-dark home" : "nav-link text-secondary about"}
to="about"
smooth={true}
offset={50}
duration={500}>
About
</Link>
</li>
<li className="nav-item">
<NavLink to="/projects">Projects</NavLink> //This is the link that won't work.
</li>
<li className="nav-item">
<Link
className={navbar ? "nav-link text-dark home" : "nav-link text-secondary contact"}
to="contact"
smooth={true}
offset={50}
duration={500}>
Contact
</Link>
</li>
</ul>
</BrowserRouter>
)
}
export default NavBar
Any help would be great!
The problem is that you're defining two different BrowserRouter. All your routing logic should be under one BrowserRouter:
App should be like this:
class App extends Component {
render() {
return (
<div className="App">
<BrowserRouter>
<NavBar />
<Switch>
<Route path="/" component={Home} exact={true} />
<Route path="/projects" component={Projects} />
</Switch>
</BrowserRouter>
</div>
);
}
}
and NavBar should not have the wrapping BrowserRouter

React Hide/Show Menu on Successful Login and Passing Information from one Component to a Component

Total Newbie in React and most of my learning is done through experimentation.
I have the following components:
App.js
import React, { Component } from 'react';
// Libraries and Utilities
import { BrowserRouter, Switch, Route } from 'react-router-dom';
// Components
import Layout from './components/layout/Layout';
import Home from './components/home/Home';
import Login from './components/login/Login';
class App extends Component {
static displayName = App.name;
render() {
return (
<BrowserRouter basename='/myapp>
<Layout>
<Switch>
<Route path="/" exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/admin' component={Admin} />
</Switch>
</Layout>
</BrowserRouter>
);
}
}
export default App;
Layout.js
import React, { Component } from 'react';
import NavMenu from '../navigation/NavMenu';
class Layout extends Component {
render() {
return (
<div className="container-fluid">
<div className="row">
<NavMenu />
</div>
<div className="main layout">
{this.props.children}
</div>
<div className="row">
<Footer />
</div>
</div>
);
}
};
export default Layout;
NavMenu.js
import React, { Component } from 'react';
import { NavLink } from "react-router-dom";
import logo from '../../assets/logo.svg';
class navigation extends Component {
constructor(props) {
super(props)
this.state = {
loggedIn: false
}
}
render() {
return (
<div className="row">
<nav className="navbar navbar-expand navbar-dark bg-primary fixed-top">
<a className="navbar-brand" href="/">
<img src={logo} width="250" height="70" alt="" />
</a>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
<li className="nav-item" to={'/'}>
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/'>Home</NavLink>
</li>
<li className="nav-item" to={'/admin1'}>
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/admin1'>Admin 1</NavLink>
</li>
<li className="nav-item" to={'/admin2'}>
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/admin1'>Admin 2</NavLink>
</li>
</ul>
<ul className="navbar-nav">
<li className="nav-item">
<NavLink exact={true} className="navbar-brand" activeClassName='active' to='/login'>
<i className="fa fa-sign-in" aria-hidden="true"></i>
</NavLink>
</li>
</ul>
</div>
</nav>
</div>
)
};
};
export default navigation;
Login .js
import React, { Component } from 'react';
class login extends Component {
constructor(props) {
super(props)
this.state = {
loginModel: {
UserName: '',
Password: ''
}
}
this.handleInputChange = this.handleInputChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleInputChange(event) {
const target = event.target
const value = target.type === 'checkbox' ? target.checked : target.value
const name = target.name
this.setState(prevState => ({
loginModel: {
...prevState.loginModel,
[name]: value
}
}))
}
handleSubmit(event) {
// At This Stage, I perform an API Call (via axios) and I get the Response Data.
const url = 'some url'
axios.post(url, this.state.loginModel).then((response) => {
if (response.status === 200) {
// Get token from response to be used in authenticated api calls.
const responseData = response.data
let authToken = responseData.token
console.log('authToken', authToken)
swal({
title: "My Application",
text: "Logon Successful.",
icon: "success"
}).then((value) => {
// Go to the Admin Home.
const path = '/admin'
this.props.history.push(path);
})
}
}, (err) => {
console.log(err.response)
const msg = err.response.data.message
const icon = err.response.data.icon
swal({
title: "My Application",
text: msg,
icon: icon
})
})
)
event.preventDefault();
}
componentDidMount() {
}
render() {
return (
<form className="form-signin" onSubmit={this.handleSubmit} >
<h3>Sign In</h3>
<div className="form-group">
<label>Username</label>
<input type="text" className="form-control" autoComplete="off"
id="input-username" name="UserName"
value={this.state.loginModel.UserName}
onChange={this.handleInputChange}
placeholder="Enter Username" />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" className="form-control" autoComplete="off"
id="input-password" name="Password"
value={this.state.loginModel.Password}
onChange={this.handleInputChange}
placeholder="Enter Password" />
</div>
<button type="submit" className="btn btn-primary btn-block">Submit</button>
</form>
)
}
}
export default login;
Home.js
import React from 'react';
import { NavLink } from "react-router-dom";
const home = (props) => {
return (
<div className="container-fluid">
<div className="fill">
<div className="row">
<div className="col-md-4 col-sm-12">
<div className="card">
<div className="card-body flex-fill">
<h5 className="card-title">Info 1</h5>
<p className="card-text">
Details about Info 1
</p>
</div>
<div className="card-footer">
<NavLink exact={true} className="btn btn-primary btn-block" to='/info1'>Start</NavLink>
</div>
</div>
</div>
<div className="col-md-4 col-sm-12">
<div className="card">
<div className="card-body flex-fill">
<h5 className="card-title">Info 2</h5>
<p className="card-text">
Details about Info 2
</p>
</div>
<div className="card-footer">
<NavLink exact={true} className="btn btn-info btn-block" to='/info2'>Browse</NavLink>
</div>
</div>
</div>
<div className="col-md-4 col-sm-12">
<div className="card">
<div className="card-body flex-fill">
<h5 className="card-title">Info 3</h5>
<p className="card-text">
Details about Info 3
</p>
</div>
<div className="card-footer">
<NavLink exact={true} className="btn btn-success btn-block" to='/info3'>View</NavLink>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default home;
My approach is quite simple. The application shows the Home component on initial load.
In the Navmenu, I have a link that navigates me to the Login screen.
In the Login screen, I have a login form where I am able to validate the user name and password via an API call.
I have multiple questions as I am still learning, but adding them here altogether as I feel it is all related.
Questions:
In my NavMenu component, I want to hide the admin1 and admin2 when on
initial load, and show it when the login is successful in the Login
component.
I want to prevent user from going to the route /admin1 and
/admin2 unless they are logged in. I am trying to read Protected
Routes but I am unable to get the hang of it as of yet.
In my Login screen, after successful login, one of the return value of the API
call is an API Key I can use for authorized calls. How can I make
that available such that I can access it from anywhere I perform an
API call.
I hope I provided enough context on what I am trying to achieve here. I know I need to brush up further my skills on how data communication between React happens.
Update: Been reading about Hooks, but I am unsure how to implement it here. Would I need to convert my JS files to use functional approach rather than class structure (ES6)?
Gracias.
I use redux for checking if use if logged in or not.
So when app start before show anything I check this.
and then I have privateRoute.
import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useSelector } from "react-redux";
function PrivateRoute({ component: Component, ...props }) {
const isAuthenticated = useSelector(state => state.User.isLogin);
return (
<Route
render={props =>
isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
{...props}
/>
);
}
export default PrivateRoute;
and define IsAuthenticated component to redirect home page if user is already logged in:
import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useSelector } from "react-redux";
function IsAuthenticated({ component: Component, ...props }) {
const isAuthenticated = useSelector(state => state.User.isLogin)
return (
<Route
{...props}
render={props =>
!isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/",
state: { from: props.location }
}}
/>
)
}
/>
);
}
export default IsAuthenticated;
and define my routes here if user must authenticated to see them:
<Router>
<Switch>
{privateRoutes.map(({ path, component: Component }, idx) => (
<PrivateRoute
key={idx}
exact
path={path}
component={() => (
<SideNav>
<Component />
</SideNav>
)}
/>
))}
<IsAuthenticated exact path="/login" component={LoginPage} />
</Switch>
</Router>
here I use SideNav in my pages, you can use redux state in your Navbar component and with checking that you can show or hide whatever you want.
Or you can define two layout for your two types of your pages.
If you don't want to use redux, you can define state in App.js and pass it to your component or use react context.
I hope I helped you in your question.

React JS - hide a text of the parent component by clicking on the NavLink

I have this parent Component that simply renders a 'p' of the introduction text and a child component called 'PortfolioMenu'
import React from 'react'
import PortfolioMenu from './PortfolioMenu'
const Portfolio = () => {
return (
<div className="wrapper2">
<p>
Here is an Introduction text
</p>
<PortfolioMenu/>
</div>
)
}
export default Portfolio
Now in the child component 'PortfolioMenu', when I click on some link of NavLink I would like to make the 'p' of the parent component 'Portfolio' disappear. How can I solve it? Thank you
import React from 'react'
import { BrowserRouter as Router, Route, NavLink } from 'react-router-dom'
import Houses from './Houses'
import Interiors from './Interiors'
const PortfolioMenu = () => {
return (
<div>
<Router>
<div class="wrapper2">
<div className="wrapper-portfolio">
<Route exact path='/portfolio/houses' render={() => <Houses />} />
<Route exact path='/portfolio/interiors' render={() =><Interiors/>}
/>
</div>
<nav>
<ul className="portfolio-menu">
<li><NavLink activeClassName="active" exact
to="/portfolio/houses">Houses</NavLink></li>
<li><NavLink activeClassName="active" exact
to="/portfolio/interiors">interiors</NavLink></li>
</ul>
</nav>
</div>
</Router>
</div>
)
}
export default PortfolioMenu
Here you go with a solution
import React from 'react'
import PortfolioMenu from './PortfolioMenu'
const Portfolio = () => {
constructor(props) {
super(props){
this.state = {
visibleP: true
};
}
this.handleMenuClick = this.handleMenuClick.bind(this);
}
handleMenuClick() {
this.setState({
visibleP: false
});
}
return (
<div className="wrapper2">
{
this.visibleP &&
<p>
Here is an Introduction text
</p>
}
<PortfolioMenu onHandleMenuClick={this.handleMenuClick}/>
</div>
)
}
import React from 'react'
import { BrowserRouter as Router, Route, NavLink } from 'react-router-dom'
import Houses from './Houses'
import Interiors from './Interiors'
const PortfolioMenu = () => {
return (
<div>
<Router>
<div class="wrapper2">
<div className="wrapper-portfolio">
<Route exact path='/portfolio/houses' render={() => <Houses />} />
<Route exact path='/portfolio/interiors' render={() =><Interiors/>}
/>
</div>
<nav>
<ul className="portfolio-menu">
<li>
<NavLink
activeClassName="active"
exact
to="/portfolio/casas"
onClick={this.props.onHandleMenuClick()}
>
casas
</NavLink>
</li>
<li>
<NavLink
activeClassName="active"
exact
to="/portfolio/interiores"
onClick={this.props.onHandleMenuClick()}
>
interiores
</NavLink>
</li>
</ul>
</nav>
</div>
</Router>
</div>
)
}
PortfolioMenu.propTypes = {
onHandleMenuClick: PropTypes.func
};
export default PortfolioMenu;
You can't have a dump component. Here you need to pass props from child component to parent component.

Categories