I am trying to get the pages by using URL but components are not rendered in the browser even I am not getting the error. So it's very hard to resolve the error.
Please Help me to get the issue.
import React, { Component } from 'react';
import { BrowserRouter as Router} from 'react-router-dom';
import Route from 'react-router-dom/Route';
class ToDoApp extends Component {
render() {
return (
<Router>
<div className="ToDoApp">
<Route path="/" exact strict Component={Index} />
<Route path="/welcome" exact strict Component={WelcomePage} />
<Route path="/login" exact strict Component={Login} />
</div>
</Router>
);
}
}
class Index extends Component {
render() {
return (<div><h1>Welcome</h1></div>);
}
}
class WelcomePage extends Component {
render() {
return (
<div>
Welcome Page
</div>
);
}
}
class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: 'Ganesh',
password: '',
hasLoginFailed: false,
showSucessMessage: false
}
this.handleChange = this.handleChange.bind(this);
this.loginCheck = this.loginCheck.bind(this);
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value // for declaring variable we use []
})
}
loginCheck() {
if (this.state.username === "Ganesh" && this.state.password === 'admin') {
console.log('successful');
this.setState({ showSucessMessage: true, hasLoginFailed: false })
} else {
console.log('failed');
this.setState({ hasLoginFailed: true, showSucessMessage: false })
}
}
render() {
return (
<div>
{/* True && 'String Value' -> String Value
False && 'String Value' -> false */}
{this.state.hasLoginFailed && <div>Invalid Login</div>}
{this.state.showSucessMessage && <div>Valid Login</div>}
UserName : <input type="text" name="username" value={this.state.username} onChange={this.handleChange} />
Password : <input type="password" name="password" value={this.state.password} onChange={this.handleChange} />
<button onClick={this.loginCheck}>Login</button>
</div>
)
}
}
export default ToDoApp
if I put localhost:3000/login -> Login Component should be displayed
if I put localhost:3000/welcome -> WelcomePage Component should be displayed
But now I am getting the blank page
import React from 'react';
import { BrowserRouter as Router, Routes, Route, } from "react-
router-dom";
import './App.css';
import Home from './components/Pages/Home';
function App() {
return (
<>
<Router>
<Routes>
<Route exact path='/' element={<Home/>}/>
</Routes>
</Router>
</>
)}
export default App;
Related
I have
<Route path='/login' exact render={() => <LoginPage sectionEmailHandler={this.sectionEmailHandler} />} />
this Route with path /login ,and i am passing callback function
sectionEmailHandler
and inside login component i am doing
this.props.history.push('/dashboard/session')
so now i am ,getting the error that
TypeError: Cannot read property 'push' of undefined
but when i did not pass the callback function with /login route like this
<Route path='/login' exact component={LoginPage} />
then it works fine.
Below is my code
Pages/index.js
import React, { Component } from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import LoginPage from '../components/Login/LoginPage'
import StartPage from '../components/startPage/StartHere'
import users from '../pages/users/index'
class Home extends Component {
// constructor(props){
// super(props)
// this.state={
// email:''
// }
// }
sectionEmailHandler=(email)=>{
console.log(email)
}
render() {
return (
<>
<Router >
<Switch>
<Route path='/' exact component={StartPage} />
<Route path='/login' exact render={() => <LoginPage sectionEmailHandler={this.sectionEmailHandler} />} />
<Route path='/dashboard/session' exact component={users} />
</Switch>
</Router>
</>
)
}
}
export default Home;
LoginPage.js
import React, { Component } from 'react'
import { Redirect } from 'react-router-dom';
import { Button,Label } from 'reactstrap';
import {Mutation, Query} from 'react-apollo';
import gql from 'graphql-tag'
import LoginPage_logo_img from '../../Assets/LoginPage_logo_img.png'
import LoginPage_email_icon from '../../Assets/LoginPage_email_icon.svg'
import LoginPage_lock_icon from '../../Assets/LoginPage_lock_icon.svg'
import './LoginPage.css'
const AUTH_USER = gql`
mutation TokenAuth($username: String!,$password : String!) {
tokenAuth(username: $username,password : $password) {
token,
payload,
refreshExpiresIn
}
}
`;
class LoginPage extends Component {
constructor(props){
super(props)
this.state={
fields: {},
errors: {},
email:'',
password:''
}
this.textInputemail = React.createRef();
this.textInputpassword = React.createRef();
}
handleValidation(){
let fields = this.state.fields;
let errors = {};
let formIsValid = true;
//Email
if(!fields["email"]){
formIsValid = false;
errors["email"] = "Please complete the field above";
}
if(typeof fields["email"] !== "undefined"){
let lastAtPos = fields["email"].lastIndexOf('#');
let lastDotPos = fields["email"].lastIndexOf('.');
if (!(lastAtPos < lastDotPos && lastAtPos > 0 && fields["email"].indexOf('##') == -1 && lastDotPos > 2 && (fields["email"].length - lastDotPos) > 2)) {
formIsValid = false;
errors["email"] = "Please enter the valid Email";
}
}
this.setState({errors: errors});
return formIsValid;
}
handleChnage=()=>{
let fields = this.state.fields;
fields[this.textInputpassword.current.name] = this.textInputpassword.current.value;
fields[this.textInputemail.current.name] = this.textInputemail.current.value;
this.setState({fields});
}
render() {
return (
<Mutation mutation={AUTH_USER}>
{(authUser,{data})=>(
<div className="LoginPage-container">
<div className="LoginPage-wrapper">
<img src={LoginPage_logo_img} alt="" className="LoginPage-logo"/>
<div className="LoginPage-email">
<img src={LoginPage_email_icon} alt=""/>
<input ref={this.textInputemail} type="email" name="email" onChange={this.handleChnage}/>
</div>
<div className="LoginPage-password">
<img src={LoginPage_lock_icon} alt=""/>
<input ref={this.textInputpassword} type="password" name="password" placeholder="Password" onChange={this.handleChnage}/>
</div>
<Button className="LoginPage-signIn" onClick={(e)=>{
e.preventDefault()
const {email,password}= this.state.fields;
authUser({
variables:{
username:email,
password:password
}
}).then((res)=>{
let token=res.data.tokenAuth.token;
localStorage.setItem('WonEToken', token);
this.props.sectionEmailHandler(email)
console.log(this.props)
this.props.router.push('/dashboard/session');
}).catch((err)=>{
console.log(err+'Error while fetching the user details');
})
}}>Sign In</Button>
<h2></h2>
</div>
</div>
)}
</Mutation>
)
}
}
export default LoginPage
Pass the route props from the Route on to the rendered component.
<Route
path='/login'
exact
render={(routeProps) => ( // <-- { history, location, match }
<LoginPage
sectionEmailHandler={this.sectionEmailHandler}
{...routeProps} // <-- spread in to component
/>
)}
/>
I assume you are using react router.
In your example
<Route path='/login' exact render={() => <LoginPage sectionEmailHandler={this.sectionEmailHandler} />} />
You need to pass in the props like this.
<Route path='/login' exact render={(props) => <LoginPage sectionEmailHandler={this.sectionEmailHandler} {...props} />} />
The props contains match, location, history
The children render prop receives all the same route props as the
component and render methods, except when a route fails to match the
URL, then match is null.
I'm new to React. I'm having trouble with getting React to recognize a prop passed in from App.js to the Login component. Specifically what I'm trying to do is getting React to do two things: 1. To check if a user is logged in. 2. What user is currently logged in. I'm using Passport, passport-local, Mongoose, MongoDB, Axios, Express, and react-router-dom to make this happen. When I attempt to log in a user I created in the database I get the following in the console:
TypeError: "this.props.updateUser is not a function"
onSubmit login.component.js:42
App.js:
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import axios from "axios";
/* Begin Import Components */
import NavigationBar from "./components/navbar.component";
import MainLanding from "./components/main-landing.component";
import Contact from "./components/general-components/contact.component";
import Register from "./components/general-components/register.component";
import Login from "./components/general-components/login.component";
import ProductsList from "./components/product-components/products-list.component";
import ProductDetails from "./components/product-components/product-details.component";
import ProductCreate from "./components/product-components/product-create.component";
import ProductEdit from "./components/product-components/product-edit.component";
import ProductDelete from "./components/product-components/product-delete.component";
import UsersList from "./components/user-components/users-list.component";
import UserDetails from "./components/user-components/user-details.component";
import OrdersList from "./components/order-components/orders-list.component";
import OrderDetails from "./components/order-components/order-details.component";
import OrderCreate from "./components/order-components/order-create.component";
import OrderEdit from "./components/order-components/order-edit.component";
/* End Import Components */
class App extends Component {
constructor(props) {
super(props);
this.state = {
loggedIn: false,
user: {}
}
this.getUser = this.getUser.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
this.updateUser = this.updateUser.bind(this)
}
getUser() {
axios.get('http://localhost:4000/logged_in').then(response => {
console.log('Get user response: ')
console.log(response.data)
if (response.data.user) {
this.setState({
loggedIn: true,
user: response.data.user
})
} else {
console.log('Get user: no user');
this.setState({
loggedIn: false,
user: {}
})
}
})
}
componentDidMount() {
this.getUser();
}
updateUser(userObject) {
this.setState(userObject)
}
render() {
return (
<Router>
<NavigationBar />
<div className="container">
{/* Begin Routes. Begin General Routes */}
<Route path="/" exact component={MainLanding} />
<Route path="/contact" exact component={Contact} />
<Route path="/register" exact component={Register} />
<Route path='/login' render={(props) => <Login {...props} />}/>
{/* End General Routes. Begin Products Routes */}
<Switch>
<Route path="/products/" exact component={ProductsList} />
<Route path="/products/new" exact component={ProductCreate} />
<Route path="/products/:id" exact component={ProductDetails} />
<Route path="/products/:id/edit" exact component={ProductEdit} />
<Route path="/products/:id/delete" exact component={ProductDelete} />
</Switch>
{/* End Products Routes. Begin Users Routes */}
<Switch>
<Route path="/users/" exact component={UsersList} />
<Route path="/users/:id" exact component={UserDetails} />
</Switch>
{/* End Users Routes. Begin Orders Routes */}
<Switch>
<Route path="/orders/" exact component={OrdersList} />
<Route path="/orders/new" exact component={OrderCreate} />
<Route path="/orders/:id" exact component={OrderDetails} />
<Route path="/orders/:id/edit" exact component={OrderEdit} />
</Switch>
{/* End Orders Routes. End Routes */}
</div>
</Router>
);
}
}
export default App;
Login Component:
import React, { Component } from "react";
import { Col, Form, Button } from "react-bootstrap";
import axios from "axios";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: ""
}
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onchangePassword = this.onchangePassword.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onchangePassword(e) {
this.setState({
password: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
axios.post("http://localhost:4000/login", {
username: this.state.username,
password: this.state.password
}).then(res => {
console.log(res)
if (res.status === 200) {
this.props.updateUser({
loggedIn: true,
username: res.data.username
})
}
}).catch(error => {
console.log(error);
});
this.setState({
username: "",
password: ""
})
this.props.history.push("/");
}
render() {
return (
<div className="text-center">
<h2>Login</h2>
<Form onSubmit={this.onSubmit}>
<Form.Row>
<Form.Group as={Col} sm={{ span: 6 }}>
<Form.Label htmlFor="formUsername">Username</Form.Label>
<Form.Control
controlid="formUsername"
type="text"
value={this.state.username}
onChange={this.onChangeUsername}
placeholder="Enter username"
/>
</Form.Group>
<Form.Group as={Col} sm={{ span: 6 }}>
<Form.Label htmlFor="formPassword">Password</Form.Label>
<Form.Control
controlid="formPassword"
type="password"
value={this.state.password}
onChange={this.onchangePassword}
placeholder="Enter password"
/>
</Form.Group>
</Form.Row>
<Button variant="success" type="submit">
Login
</Button>
</Form>
</div>
)
}
}
export default Login;
Let me know if I need to provide any additional information. Thank you.
The function updateUser() is defined correctly but you need to pass it to the Login component:
App.js
<Route path='/login' render={(props) =>
<Login {...props} updateUser={this.updateUser} />
}/>
This will append props.updateUser to the Login component on top of all the props from the parent component (App.js).
It does seem to be that you still not put updateUser as props of Login component. You could try like this
<Route path='/login' render={(props) =>
<Login {...props} updateUser={this.updateUser} />
}/>
But, i think that this.props.updateUser() may also be come from redux of application (mapDispatchtoProps). If so, you just connect Login component to redux, don't need to put this function as props in Login component.
I don't know where I'm going wrong
by clicking the enter button I validate my user and use this.props.history.push ("/ home");
and it doesn't work
my login . js
class LoginForm extends Component {
constructor(props){
super(props);
this.state = {
login:'',
password:'',
};
this.onSubmit = this.onSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
async onSubmit(e){
e.preventDefault();
const {login, password } = this.state;
const response = await api.post('/login', { login,password });
const user = response.data.user.login;
const {jwt} = response.data;
localStorage.setItem('token', jwt);
localStorage.setItem('user', user);
this.props.history.push("/home");
}
onChange(e){
this.setState({[e.target.name]: e.target.value});
}
render() {
const { errors, login, password, isLoading } = this.state;
return (
<form onSubmit={this.onSubmit}>
<label htmlFor="login">Login</label>
<input type="text" name="login" id="login" value={login} onChange={(e) => this.onChange(e)} placeholder="Informe seu login" />
<label htmlFor="password">Senha</label>
<input type="password" name="password" id="password" value={password} onChange={(e) => this.onChange(e)} placeholder="Informe sua senha"/>
<button className="btnEnt" type="submit">Entrar</button>
</form>
)
}
}
export default LoginForm;
my router . js:
import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Login from './pages/login/index';
import DashBoard from './pages/dashboard/index';
import PrivateRoute from './auth';
export default function Routes(){
console.log('a')
return(
<BrowserRouter>
<Switch>
<PrivateRoute path="/home" component = {DashBoard}/>
</Switch>
</BrowserRouter>
);
} <PrivateRoute path="/home" component = {DashBoard}/>
</Switch>
</BrowserRouter>
);
}
my auth . js :
import { Route, Redirect} from 'react-router-dom';
const isAuth = () => {
console.log('a');
if(localStorage.getItem('token') !== null) {
return true;
}
return false;
};
const PrivateRoute = ({component: Component, ...rest}) => {
return (
<Route
{...rest}
render={props =>
isAuth() ? (
<Component {...props} />
): (
<Redirect
to={{
pathname: '/',
state: {message: 'Usuário não autorizado'}
}}
/>
)}
/>
);
}
export default PrivateRoute;
my dashboard / index
import React, { Component } from 'react';
import Home from '../../components/Home';
class DashBoard extends Component {
render() {
return (
<Home />
)
}
}
export default DashBoard;
error:
Unhandled Rejection (TypeError): Cannot read property 'push' of
undefined
Uncaught (in promise) TypeError: Cannot read property 'push' of
undefined I really do not know what I can is wrong is not redirecting,
I have tried all possible alternatives.
Before you can use history in your React component, you need to wrap it in withRouter.
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md
import history from 'add your path'
export default function Routes() {
console.log('a')
return (
<BrowserRouter history={history}>
<Switch>
<PrivateRoute exact path="/home" component={DashBoard} />
</Switch>
</BrowserRouter>
)
}
do changes in router file
import { withRouter } from 'react-router-dom';
export default withRouter(LoginForm);
add withRouter in this component
I am a beginner in React.js and I am using Firebase & React Router. I have set up a separate Auth.js file (exporting a boolean) where I store the authenticated state of a user and it works as intended but the problem is that when I login/register or logout the content doesn't change/re-render. Logging the exported boolean in other files I see that it doesn't change for some reason.
Auth
import fire from './Fire';
var isAuth = false;
fire.auth().onAuthStateChanged(
function (user) {
if (user) {
isAuth = true;
console.log('Authed');
} else {
isAuth = false
console.log('Not Auth');
}
}
);
export default isAuth;
Then there's Router.js
import React, { Component } from 'react';
import { Route, Switch, Redirect } from "react-router-dom";
import Login from './components/common/Navbar/Login/Login';
import Register from './components/common/Navbar/Register/Register';
import Home from './components/common/Home/Home';
import isAuth from './config/isAuth';
import All from './components/All/All';
import PrivateRoute from './config/PrivateRoute';
class Router extends Component {
constructor(props) {
super(props);
this.state = ({
isAuth: isAuth
});
}
componentWillMount() {
this.setState = ({
isAuth: isAuth
});
}
render() {
console.log('Router.js => ' + this.state.isAuth)
return (
<div>
<PrivateRoute exact path='/' component={Home} />
<PrivateRoute exact path='/register' component={
this.state.isAuth ? Home : Register} />
<PrivateRoute exact path='/all' component={All} />
<Route exact path='/login' component={ this.state.isAuth ? Home : Login} />
</div>
);
}
}
export default Router;
And finally PrivateRoute component which I took from someone's code on the internet.
import React from 'react';
import { Redirect, Route } from "react-router-dom";
const PrivateRoute = ({ component: Component, ...rest }, isLogged) => (
<Route {...rest} render={(props) => (
isLogged
? (<Component {...props} /> )
: (<Redirect to={{ pathname: '/login' }} />)
)} />
)
export default PrivateRoute;
To fix this issue I changed a few things in the way you handled auth state change. See changes below:
Router.js
...
class Router extends Component {
constructor(props) {
super(props);
this.state = {
isAuth: false
};
}
componentDidMount() {
fire.auth().onAuthStateChanged(user => {
console.log("Router user", user);
if (user) {
localStorage.setItem("user", user); // Note the use of localStorage
this.setState({ isAuth: true });
}
});
}
render() {
return (
<div>
<Switch>
<PrivateRoute
exact
path="/"
component={Home}
isLogged={this.state.isAuth}
/>
<PrivateRoute
exact
path="/register"
component={this.state.isAuth ? Home : Register}
isLogged={this.state.isAuth}
/>
<PrivateRoute
exact
path="/all"
component={All}
isLogged={this.state.isAuth}
/>
<Route
exact
path="/login"
component={this.state.isAuth ? Home : Login}
/>
</Switch>
</div>
);
}
}
export default Router;
Take note of the isLogged prop I passed to the PrivateRoute components, this ensures that the current auth state is accessible from within PrivateRoute component. I also used the localStorage to persist the auth state.
PrivateRoute.js
...
const PrivateRoute = ({ component: Component, ...rest }, isLogged) => (
<Route
{...rest}
render={props =>
rest.isLogged ? (
<Component {...props} />
) : (
<Redirect to={{ pathname: "/login" }} />
)
}
/>
);
export default PrivateRoute;
You would notice that I am using rest.isLogged instead of the isLogged argument which for some reason is always undefined. rest.isLogged was passed into this component from the Router component.
Home.js
class Home extends Component {
constructor(props) {
super(props);
this.state = {
isAuth: localStorage.getItem("user") || false
};
console.log("Home.js => " + this.state.isAuth);
}
render() {
return (
<div>
{/* If logged => Welcome ; else => Login */}
{this.state.isAuth ? <Welcome /> : <Login />}
</div>
);
}
}
export default Home;
In Home component, I removed the isAuth import as it was not working, then I set state's isAuth to get the user from localStorage.
From here on out, I'm sure you can figure the rest of your app out. Peace.
Click on the button below to view on codesandbox
I think the way you do will not change the isAuth state. Can you try this solution? I hope it will work
class Router extends Component {
constructor(props) {
super(props);
this.state = ({
isAuth: false
});
}
componentDidMount() {
fire.auth().onAuthStateChanged((user) => {
if (user) {
console.log(user);
this.setState({ isAuth: true });
} else {
this.setState({ isAuth: false });
}
});
}
render() {
console.log('Router.js => ' + this.state.isAuth)
return (
<div>
<PrivateRoute exact path='/' component={Home}/>
<PrivateRoute exact path='/register' component={
this.state.isAuth ? Home : Register} />
<PrivateRoute exact path='/all' component={All}/>
<Route exact path='/login' component={ this.state.isAuth ? Home : Login} />
</div>
);
}
}
I want to redirect to my home route upon submitting my axios request to the api and gathering a valid response. As can be seen, Im trying to use context but in this case i get an error "context is undefined". How can i navigate to my home route in this case? I tried using history.push but that does not seem to work either. Any ideas would be much appreciated?
import React, {Component} from 'react'
import axios from 'axios'
import Home from './Home'
import {
BrowserRouter,
Link,
Route
} from 'react-router-dom'
class SignUp extends Component {
constructor(props){
super(props);
this.state = {
email: '',
password: ''
};
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
handleClick = () => {
axios
.post('http://localhost:9000/signup',{
email: this.state.email,
password: this.state.password
}).then(function(response){
console.log(response.data.success)
this.context.router.push('/home');
})
}
render(){
return(
<BrowserRouter>
<Route path="/" render={() => (
<div>
<h1> Sign Up</h1>
<input name="email" placeholder="enter your email" onChange={e => this.handleChange(e)}/>
<br/>
<input name="password" placeholder="enter your password" onChange={e => this.handleChange(e)}/>
<br/>
<button onClick={() => this.handleClick()}>submit</button>
<Route exact path="/home" component={Home}/>
</div>
)}/>
</BrowserRouter>
)
}
}
SignUp.contextTypes = {
router: React.PropTypes.func.isRequired
};
export default SignUp
Routes should be always level above of all your components (or containers). Then, when a component is "inside" router (in your case BrowserRouter) it will gain access to its context.
Also you have inside render function of another wich does not make sense at all.
So something like this should work:
import React, {Component} from 'react'
import axios from 'axios'
import Home from './Home'
import {
BrowserRouter,
Link,
Route
} from 'react-router-dom'
class SignUp extends Component {
constructor(props){
super(props);
this.state = {
email: '',
password: ''
};
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
handleClick = () => {
axios
.post('http://localhost:9000/signup',{
email: this.state.email,
password: this.state.password
}).then(function(response){
console.log(response.data.success)
this.context.router.push('/home');
})
}
render(){
return(
<div>
<h1> Sign Up</h1>
<input name="email" placeholder="enter your email" onChange={e => this.handleChange(e)}/>
<br/>
<input name="password" placeholder="enter your password" onChange={e => this.handleChange(e)}/>
<br/>
<button onClick={() => this.handleClick()}>submit</button>
</div>
)
}
}
SignUp.contextTypes = {
router: React.PropTypes.func.isRequired
};
class App extends Component {
render() {
return(
<BrowserRouter>
<Route path="/" component={SignUp} />
<Route exact path="/home" component={Home}/>
</BrowserRouter>)
}
}
export default App;
And of course move SignUp component to standalone file to keep the project clean and well structured.