how to create login page in react-redux using axios - javascript

I've created login page, but my issue is after clicking the submit button it is not redirecting my main Dashboard page.
Authentication/login.js
import React, { Component } from 'react'
import { Field, reduxForm } from 'redux-form';
import renderField from 'components/FormInputs/renderField';
import axios from "axios";
import { Route, router } from 'react-router-dom';
import { withRouter } from 'react-router-dom';
class Login extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
}
}
changeHandler = e => {
this.setState({ [e.target.name]: e.target.value })
}
submitHandler = e => {
e.preventDefault()
console.log(this.state)
`axios.post('http://localhost/api/validuser2', {
user: {
"email": this.state.email,
"password": this.state.password
}
},
{ withCredentials: true })`
.then(res => {
console.log(res.data[0])
if (res.data[0] === true) {
alert('Login Successful')
`this.props.handleSuccessfulAuth(res.data[0])`
alert('Logged in')
}
})
.catch(error => {
console.log(error)
})
}
render() {
const { email, password } = this.state
return (
<div className="card">
<div className="header">
<h4>Login</h4>
</div>
<div className="content">
<form className="form-horizontal" onSubmit = {this.submitHandler} >
<div className="form-group">
<label className="control-label col-md-3">Email</label>
<div className="col-md-9">
<Field
name="email"
type="email"
value={email}
//error={errors.email}
component={renderField}
onChange={ this.changeHandler } />
</div>
</div>
<div className="form-group">
<label className="control-label col-md-3">Password</label>
<div className="col-md-9">
<Field
name="password"
type="password"
value={password}
//error={errors.password}
component={renderField}
onChange={ this.changeHandler } />
</div>
</div>
<button className="btn btn-success btn-fill btn-wd">Success</button>
</form>
</div>
</div>
)
}
}
export default reduxForm({
form: 'formElements'
})(Login);
Authentication/index.js
import React, { Component } from 'react';
import Login from './Login';
import Footer from './Footer';
class Authentication extends Component {
constructor(props) {
super(props);
this.handleSuccessfulAuth = this.handleSuccessfulAuth.bind(this);
}
handleSuccessfulAuth(data) {
this.props.handleLogin(data);
`this.props.history.push("../main")`
}
render() {
return (
<div className="wrapper">
<div className="content">
<div className="container-fluid">
<div className="row-md-2">
<div className="col-md-8">
<div className="main-panel">
<Login handleSuccessfulAuth={this.handleSuccessfulAuth} />
</div>
</div>
<div className="main-panel">
<Footer />
</div>
</div>
</div>
</div>
</div>
)
}
}
export default Authentication;
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import { HashRouter } from 'react-router-dom';
import './assets/styles/base.scss';
import 'sweetalert/dist/sweetalert.css';
import Authentication from './pages/Authentication';
import configureStore from './config/configureStore';
import { Provider } from 'react-redux';
const store = configureStore();
const rootElement = document.getElementById('root');
const renderApp = Component => {
ReactDOM.render(
<Provider store={store}>
<HashRouter>
<Component />
</HashRouter>
</Provider>,
rootElement
);
};
renderApp(Authentication);
if (module.hot) {
`module.hot.accept('./pages/Authentication', () => {
const NextApp = require('./pages/Authentication').default
renderApp(NextApp);`
});
}
registerServiceWorker();

can use window.location.href and also this.props.history.push("../dashboard")
submitHandler = e => {
e.preventDefault()
console.log(this.state)
`axios.post('http://localhost/api/validuser2', {
user: {
"email": this.state.email,
"password": this.state.password
}
},
{ withCredentials: true })`
.then(res => {
console.log(res.data[0])
if (res.data[0] === true) {
alert('Login Successful')
//window.location.href = dashboardUrl;
`this.props.handleSuccessfulAuth(res.data[0])`
alert('Logged in')
}
})
.catch(error => {
console.log(error)
})
}

Related

React Js renderings is functionalities not working

I am new to react . I am hared coded the username and password into js pages . I am trying to redirect to user into admin pages on the text fields values. Here is mentioned that username and password Admin then i want to redirect the user into admin page else into home page but is not working . I also defined the router as well into app.js files.
Here is the app.js .
import React from 'react';
import { Router, Route, Switch, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { history } from '../_helpers';
import { alertActions } from '../_actions';
import { PrivateRoute } from '../_components';
import { HomePage } from '../HomePage';
import { LoginPage } from '../LoginPage';
import { RegisterPage } from '../RegisterPage';
import CreateEmployeeComponent from '../EmployeeComponets/CreateEmployeeComponent';
import ViewEmployeeComponent from '../EmployeeComponets/ViewEmployeeComponent';
import AdminComponent from '../EmployeeComponets/AdminComponent';
class App extends React.Component {
constructor(props) {
super(props);
history.listen((location, action) => {
// clear alert on location change
this.props.clearAlerts();
});
}
render() {
const { alert } = this.props;
return (
<div className="jumbotron">
<div className="container">
<div className="col-sm-8 col-sm-offset-2">
{alert.message &&
<div className={`alert ${alert.type}`}>{alert.message}</div>
}
<Router history={history}>
<Switch>
<PrivateRoute exact path="/" component={HomePage} />
<Route path = "/add-employee/:id" component = {CreateEmployeeComponent} />
<Route path = "/view-employee/:id" component = {ViewEmployeeComponent} />
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<Route path ="/admin" component={AdminComponent} />
<Redirect from="*" to="/" />
</Switch>
</Router>
</div>
</div>
</div>
);
}
}
function mapState(state) {
const { alert } = state;
return { alert };
}
const actionCreators = {
clearAlerts: alertActions.clear
};
const connectedApp = connect(mapState, actionCreators)(App);
export { connectedApp as App };
Here is the code for Login.js
import React from 'react';
import { Link, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { userActions } from '../_actions';
class LoginPage extends React.Component {
constructor(props) {
super(props);
// reset login status
this.props.logout();
this.state = {
username: '',
password: '',
submitted: false
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
const { name, value } = e.target;
this.setState({ [name]: value });
}
handleSubmit(e) {
e.preventDefault();
this.setState({ submitted: true });
const { username, password } = this.state;
if (username && password) {
this.props.login(username, password);
}
else if(username==="Admin" && password==="Admin"){
localStorage.setItem("token" , "shjsshhbhbh")
this.setState({
loggingIn:true
})
}
}
render() {
if(this.state.loggingIn){
return <Redirect to ="/admin" />
}
const { loggingIn } = this.props;
const { username, password, submitted } = this.state;
return (
<div className="col-md-6 col-md-offset-3">
<h2>Login</h2>
<form name="form" onSubmit={this.handleSubmit}>
<div className={'form-group' + (submitted && !username ? ' has-error' : '')}>
<label htmlFor="username">Username</label>
<input type="text" className="form-control" name="username" value={username} onChange={this.handleChange} />
{submitted && !username &&
<div className="help-block">Username is required</div>
}
</div>
<div className={'form-group' + (submitted && !password ? ' has-error' : '')}>
<label htmlFor="password">Password</label>
<input type="password" className="form-control" name="password" value={password} onChange={this.handleChange} />
{submitted && !password &&
<div className="help-block">Password is required</div>
}
</div>
<div className="form-group">
<button className="btn btn-primary">Login</button>
{loggingIn &&
}
<Link to="/register" className="btn btn-link">Register</Link>
</div>
</form>
</div>
);
}
}
function mapState(state) {
const { loggingIn } = state.authentication;
return { loggingIn };
}
const actionCreators = {
login: userActions.login,
logout: userActions.logout
};
const connectedLoginPage = connect(mapState, actionCreators)(LoginPage);
export { connectedLoginPage as LoginPage };
Here is the private route code
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
export const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
localStorage.getItem('user')
? <Component {...props} />
: <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
)} />
)
Here is the admin page .
import React, { Component } from 'react'
import { Redirect } from 'react-router-dom';
import EmployeeService from '../services/EmployeeService';
class AdminComponent extends Component {
constructor(props) {
super(props)
const token =localStorage.getItem("token")
let loggedIn = true
{
if(token == null){
loggedIn - false
}
this.state ={
loggedIn
}
}
this.state = {
// step 2
id: this.props.match.params.id,
firstName: '',
lastName: '',
emailId: ''
}
this.changeFirstNameHandler = this.changeFirstNameHandler.bind(this);
this.changeLastNameHandler = this.changeLastNameHandler.bind(this);
this.saveOrUpdateEmployee = this.saveOrUpdateEmployee.bind(this);
}
// step 3
componentDidMount(){
// step 4
if(this.state.id === '_add'){
return
}else{
EmployeeService.getEmployeeById(this.state.id).then( (res) =>{
let employee = res.data;
this.setState({firstName: employee.firstName,
lastName: employee.lastName,
emailId : employee.emailId
});
});
}
}
saveOrUpdateEmployee = (e) => {
e.preventDefault();
let employee = {emailId: this.state.emailId,firstName: this.state.firstName, lastName: this.state.lastName};
console.log('employee => ' + JSON.stringify(employee));
// step 5
if(this.state.id === '_add'){
EmployeeService.createEmployee(employee).then(res =>{
this.props.history.push('/employees');
});
}else{
EmployeeService.updateEmployee(employee, this.state.id).then( res => {
this.props.history.push('/employees');
});
}
}
changeFirstNameHandler= (event) => {
this.setState({firstName: event.target.value});
}
changeLastNameHandler= (event) => {
this.setState({lastName: event.target.value});
}
changeEmailHandler= (event) => {
this.setState({emailId: event.target.value});
}
cancel(){
this.props.history.push('/employees');
}
getTitle(){
if(this.state.id === '_add'){
return <h3 className="text-center">Add Employee</h3>
}else{
return <h3 className="text-center">Update Employee</h3>
}
}
render() {
if(this.state.loggedIn === false)
{
return <Redirect to ="/login" />
}
return (
<div>
<h1>Welcome to adimin </h1>
<br></br>
<div className = "container">
<div className = "row">
<div className = "card col-md-6 offset-md-3 offset-md-3">
{
this.getTitle()
}
<div className = "card-body">
<form>
<div className = "form-group">
<label> Email Id: </label>
<input placeholder="Email Address" name="emailId" className="form-control"
value={this.state.emailId} onChange={this.changeEmailHandler}/>
</div>
<div className = "form-group">
<label> First Name: </label>
<input placeholder="First Name" name="firstName" className="form-control"
value={this.state.firstName} onChange={this.changeFirstNameHandler}/>
</div>
<div className = "form-group">
<label> Last Name: </label>
<input placeholder="Last Name" name="lastName" className="form-control"
value={this.state.lastName} onChange={this.changeLastNameHandler}/>
</div>
<button className="btn btn-success" onClick={this.saveOrUpdateEmployee}>Save</button>
<button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{marginLeft: "10px"}}>Cancel</button>
</form>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default AdminComponent
in your handleSubmit function always first if is true and after that javascript didn't check another else if.
Also you need add another state isAdmin and use it like this:
const { username, password } = this.state;
if (username==="Admin" && password==="Admin") {
this.props.login(username, password);
localStorage.setItem("token" , "adminsaddad")
this.setState({
loggingIn:true,
isAdmin:true
})
} else if (username && password) {
this.props.login(username, password);
localStorage.setItem("token" , "shjsshhbhbh")
this.setState({
loggingIn:true
})
}
Then check if the user is admin or not:
if(this.state.loggingIn){
if(this.state.isAdmin)
return <Redirect to ="/admin" />
else
return <Redirect to ="/" />
}
But this is not a safe way for the admin page, should also add the admin component in your PrivateRoute and check the token then redirect user.

React: How to redirect

I am a beginner in React and was implementing a function where on a button click in the render method, I go to a function foo. In that function, I am sending the username and password to a server.
If the username and password are correct, it returns a JSON object like
{"Result":1,"Cookie":"COOKIE!!!"}
I am trying to redirect it to another class component I have made (Flood) if result is 1. Can someone kindly help me
I tried redirecting it after render and before return but I get an error
Error: Invariant failed: You should not use <Redirect> outside a <Router>
import React from 'react';
import './style.scss';
import LoginImage from './LoginImage.png'
import Button from 'react-bootstrap/Button'
import Form from 'react-bootstrap/Form'
import {Redirect, Router} from 'react-router-dom'
//import Logfailed from './Logfailed'
import Flood from './Flood'
class UserLogin extends React.Component {
constructor(props) {
super(props);
this.state = {userName:'', password:'', act:'l', flag:0, txt:''};
this.handleChange1 = this.handleChange1.bind(this);
this.handleChange2 = this.handleChange2.bind(this);
this.handleClick = this.handleClick.bind(this);
}
async handleClick(e) {
const url = 'http://52.8.557.164/user'
const data = {username:this.state.userName, password:this.state.password, action:this.state.act};
try {
const response = await fetch(url,
{
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
},
});
const json = await response.json();
if(json['Result'] === 1) {
this.setState({flag: 1, txt:''});
}
else {
this.setState({flag:2, txt:'Wrong username and Password'});
}
console.log('Success', JSON.stringify(json));
console.log(json['Cookie']);
} catch (error) {
console.error('Error', error);
}
}
handleChange1(e) {
this.setState({userName: e.target.value})
}
handleChange2(e) {
this.setState({password: e.target.value})
}
render() {
if (this.state.flag === 1) {
return <Redirect to='/Flood' />
}
return (
<div className = 'outer-container' ref={this.props.containerRef}>
<div className = 'header'> Login </div>
<div className="content">
<div className="image">
<img src={LoginImage} />
</div>
<Form className = 'form'>
<Form.Group controlId="formBasicEmail" className = 'form-group'>
<Form.Label style={{marginTop: '90px'}}>Username</Form.Label>
<Form.Text className="text-muted" htmlFor="username"></Form.Text>
<input type="text" value = {this.state.userName} name="username" placeholder="username" onChange={this.handleChange1}/>
</Form.Group>
<Form.Group controlId="formBasicPassword" className = 'form-group'>
<Form.Label>Password</Form.Label>
<Form.Text className="text-muted" htmlFor="password"></Form.Text>
<input type="password" value = {this.state.password} name="password" placeholder="password" onChange={this.handleChange2} />
<br></br>
<span>{this.state.txt}</span>
</Form.Group>
</Form>
</div>
<div className="footer">
<Button variant="outline-primary" size="lg" onClick={this.handleClick} className="btn" block>
Login
</Button>
</div>
</div>
);
}
}
export default UserLogin;
import React from 'react';
class Flood extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<h1>gg</h1>
)}
}
export default Flood;
import React from 'react';
import './App.css';
import UserLogin from './UserLogin';
import Register from './Register'
import { Router, Redirect} from 'react-router-dom'
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
login: true
};
}
componentDidMount() {
this.rightSide.classList.add("right");
}
changeState() {
const { login } = this.state;
if (login) {
this.rightSide.classList.remove("right");
this.rightSide.classList.add("left");
} else {
this.rightSide.classList.remove("left");
this.rightSide.classList.add("right");
}
this.setState(prevState => ({ login: !prevState.login }));
}
render() {
const {login} = this.state;
const curr = login ? "Register" : "Login";
const currentActive = login ? "login" : "register";
return (
<div className="App">
<div className="login">
<div className="container" ref={ref => (this.container = ref)}>
{login && (
<UserLogin containerRef={ref => (this.curr = ref)} />
)}
{!login && (
<Register containerRef={ref => (this.curr = ref)} />
)}
</div>
<RightSide
curr={curr}
currentActive={currentActive}
containerRef={ref => (this.rightSide = ref)}
onClick={this.changeState.bind(this)}
/>
</div>
</div>
);
}
}
const RightSide = props => {
return (
<div
className="right-side"
ref={props.containerRef}
onClick={props.onClick}
>
<div className="inner-container">
<div className="text">{props.curr}</div>
</div>
</div>
);
};
export default App;
BrowserRouter is the provider to be used in React Router for usage of anything related to routing. To add it to your component:
import { BrowserRouter as Router } from "react-router-dom";
class App extends React.Component {
render() {
return (
<Router>
// Rest of the App component here.
</Router>
);
}
}
Note that there needs to be only one wrapping Router in an application (generally) and hence it makes sense to wrap the entry component in it.
Basic Routing Example - React Routing
First of all, you need to wrap your component using withRouter tag
import { withRouter } from 'react-router-dom'
then wrap your component/class when you're exporting
export default withRouter(yourComponent);
ok, now back to the issue:
To redirect, you can simply push something to the history object
history.push('/redirect-location');

React/Redux: redirect after loggin

Am new to react/redux.I have a Redux action for authentication, and after that I need to redirect to a confirmation page home. I don't know how to redirect
this is my index.js
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { createStructuredSelector } from 'reselect';
import {loginAction} from './actions';
export class Login extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
// this.handleChange = this.handleChangeUsername.bind(this);
// this.handleSubmit = this.handleChangePassword.bind(this);
}
handleChangeUsername(event) {
console.log(event.target.value);
this.setState({username: event.target.value});
console.log(this.state.username)
}
handleChangePassword(event) {
this.setState({password: event.target.value});
console.log(this.state.password)
}
handleSubmit(event) {
this.props.dispatch(loginAction(this.state));
event.preventDefault();
}
render() {
return (
<div>
<div className="loginColumns animated fadeInDown">
<div className="row">
<div className="col-md-6">
</div>
<div className="col-md-6">
<div className="ibox-content">
<form className="m-t" role="form" onSubmit={this.handleSubmit.bind(this)}>
<div className="form-group">
<input type="email" value={this.state.username} onChange={this.handleChangeUsername.bind(this)} className="form-control" placeholder="Username" required="" />
</div>
<div className="form-group">
<input type="password" value={this.state.password} onChange={this.handleChangePassword.bind(this)} className="form-control" placeholder="Password" required="" />
</div>
<button type="submit" className="btn btn-primary block full-width m-b">Login</button>
<a href="#">
<small>Forgot password?</small>
</a>
</form>
</div>
</div>
</div>
<hr/>
<div className="row">
<div className="col-md-6">
Copyright Example Company
</div>
<div className="col-md-6 text-right">
<small>© 2014-2015</small>
</div>
</div>
</div>
</div>
);
}
}
Login.propTypes = {
dispatch: PropTypes.func.isRequired,
};
const mapStateToProps = createStructuredSelector({
// Login: makeSelectLogin(),
});
function mapDispatchToProps(dispatch) {
return {
dispatch,
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
action.js
import {
DEFAULT_ACTION,
LOGIN_ACTION
} from './constants';
export function defaultAction() {
return {
type: DEFAULT_ACTION,
};
}
export function loginAction(json) {
return {
type: LOGIN_ACTION,
json
};
}
reducer.js
import { fromJS } from 'immutable';
import {
DEFAULT_ACTION,
LOGIN_ACTION
} from './constants';
const initialState = fromJS({
status: false
});
function loginReducer(state = initialState, action) {
console.log("action", action)
switch (action.type) {
case DEFAULT_ACTION:
return state;
case LOGIN_ACTION:
return _testFunction(state,action.json);
default:
return state;
}
}
function _testFunction(state, json) {
if(json.username == "abcd#gmail.com" && json.password == "1234")
return state.set("status", true)
}
export default loginReducer;
i want to redirect /home after successful login. how can i redirect?
Well, what you have to do is something like this. Pass a callback to your action. Once action completed it work, merely invoke that callback, which will programmatically redirect you to the url you need. Upon the submission of the login form pass the input values with the callback function to your action like this.
onSubmit(values) {
this.props.loginAction(values, () => {
this.props.history.push('/');
});
}
Then in your action, if you are calling a backend API, when the promise is resolved make sure you invoke the callback function that gets passed in to the action like this.
export function loginAction(values, callback) {
const request = axios.post(`/endpoint`, values)
.then(() => callback());
return {
type: LOGIN,
payload: request
};
}
This is all what you have to do. It is up to you to make slight alterations to this depending on your scenario and setup. I'll keep it for you as an exercise. Hope this helps. Happy Coding !

How do I go to a new path after signing up in React

I'm new to React, I'm building an Electron app.
In the code below, I check to see if there's a signed in user, and if so, I render Home, if they haven't logged in yet or signed up, I render SignIn
(this code lives in app.js)
if (JSON.parse(localStorage.cookies).user_id === undefined) {
render((
<Provider store={store}>
<SignIn />
</Provider>
), document.getElementById('content'));
} else {
render((
<Provider store={store}>
<Home />
</Provider>
), document.getElementById('content'));
}
When the user signs up or logs in, I want to take them to Home right afterwards. I can do that in development my refreshing my Electron window. How do I achieve this in my code?
Here is the code for SignIn.js
import React, { Component, PropTypes } from 'react';
import {connect} from 'react-redux';
import {signUp, logIn} from '../entities/auth/actions';
class SignIn extends Component {
constructor(props) {
super(props);
this.logIn = this.logIn.bind(this);
this.signUp = this.signUp.bind(this);
this.state = {
registration: {
username: '',
password: '',
email: '',
},
login: {
username: '',
password: '',
},
};
}
signUp() {
this.props.dispatch(signUp(this.state.registration));
}
logIn() {
this.props.dispatch(logIn(this.state.login));
}
render() {
const {registration, login} = this.state;
return (
<div className="sign-in">
<h1>MyApp</h1>
<form id="login-form" onSubmit={(e) => {
e.preventDefault();
}}>
<input type="username" value={login.username} placeholder="Enter username" onChange={e => this.setState({login: {...login, username: e.target.value}})}/>
<input type="password" value={login.password} placeholder="Enter password" onChange={e => this.setState({login: {...login, password: e.target.value}})}/>
<button onClick={this.logIn}>Log in</button>
</form>
<form id="registration-form" onSubmit={(e) => {
e.preventDefault();
}}>
<input type="text" value={registration.username} placeholder="Enter user name" onChange={e => this.setState({registration: {...registration, username: e.target.value}})}/>
<input type="password" value={registration.password} placeholder="Enter password" onChange={e => this.setState({registration: {...registration, password: e.target.value}})}/>
<input type="email" value={registration.email} placeholder="Enter email" onChange={e => this.setState({registration: {...registration, email: e.target.value}})}/>
<button onClick={this.signUp}>Sign up</button>
</form>
</div>
);
}
}
SignIn.propTypes = {
dispatch: PropTypes.func,
};
const mapStateToProps = () => {
return {};
};
export default connect(mapStateToProps)(SignIn);
Thanks!
Assuming you don't want to use react-router, a way to approach this problem would be to have a higher component that renders either Login or Home by checking the cookies. This component could have a state value loggedIn. For example:
class Application extends React.Component {
constructor(props) {
super(props);
this.handleLogin = this.handleLogin.bind(this);
const isLoggedIn = JSON.parse(localStorage.cookies).user_id === undefined;
this.state = {
loggedIn: isLoggedIn,
}
}
handleLogin() {
//if login was successful, do:
this.setState({ loggedIn: true })
}
render() {
return (
<div>
{
this.state.loggedIn
? <Home />
: <LoggedIn handleLogin={this.handleLogin}>
}
</div>
)
}
}
Then trigger handleLogin in your Login component somehow:
signUp() {
this.props.dispatch(signUp(this.state.registration, this.props.handleLogin));
}
logIn() {
this.props.dispatch(logIn(this.state.login, this.props.handleLogin));
}
render() {
const {registration, login} = this.state;
This will update the parent state and rerender the appropriate component.
Also need to change
render((
<Provider store={store}>
<Application />
</Provider>
), document.getElementById('content'));

How to use facebook/google login button to store user information with react redux

I want to use facebook/goolge login button to automatically store user's information to the server. Right now, it seems that the information has been passed to the API part (I mean at least the program tried...). In most of the cases there is no error, but the login page is blank, but I still received this kind of error message.
bundle.js:72621 Uncaught ReferenceError: FB is not defined
at FacebookButton.componentDidMount (bundle.js:72621)
at CallbackQueue.notifyAll (bundle.js:6532)
at ReactReconcileTransaction.close (bundle.js:16290)
at ReactReconcileTransaction.closeAll (bundle.js:6893)
at ReactReconcileTransaction.perform (bundle.js:6840)
at batchedMountComponentIntoNode (bundle.js:2740)
at ReactDefaultBatchingStrategyTransaction.perform (bundle.js:6827)
at Object.batchedUpdates (bundle.js:10864)
at Object.batchedUpdates (bundle.js:6332)
at Object._renderNewRootComponent (bundle.js:2934)
Here is the code for my action part:
import { FACEBOOKLOGIN } from "../constants/index";
const API_URL = "http://localhost:3000";
//FACEBOOKLOGIN
export function facebookLogin(props){
const request = axios.post(`${API_URL}/users`,{
user: {
email:props.email,
password:props.password,
password_confirmation:props.password
}
});
return{
type: FACEBOOKLOGIN,
payload: request
}
}
and here is my facebook login function
import React, { Component, PropTypes }from 'react';
import { reduxForm } from 'redux-form';
import { facebookLogin } from '../../actions/index';
import { FACEBOOKLOGIN } from '../../constants/index';
var password = {password: "zsy2053#gmail.com"};
function validate(values) {
const errors = {}
if (!values.password) {
values.password = password;
}
return errors
}
class FacebookButton extends React.Component {
static contextTypes = {
router: PropTypes.object
};
constructor(props) {
super(props);
this.FB = props.fb;
this.state = {
message: ""
};
this.onClick = this.onClick.bind(this);
}
onClick(props){
this.props.facebookLogin(props)
.then(() => {
this.context.router.push('/');
});
}
componentDidMount() {
FB.Event.subscribe('auth.logout',
this.onLogout.bind(this));
FB.Event.subscribe('auth.statusChange',
this.onStatusChange.bind(this));
}
onStatusChange(response) {
console.log( response );
var self = this;
if( response.status === "connected" ) {
FB.api('/me', { locale: 'tr_TR', fields: 'name, email,birthday, hometown,education,gender,website,work' },
function(response) {
console.log(response.email);
console.log(response.name);
console.log(response.gender);
console.log(response.birthday);
console.log(response.hometown);
console.log(response.education);
console.log(response.website);
console.log(response.work);
var message;
self.setState({
message: response.email
});
})
}
}
onLogout(response) {
this.setState({
message: ""
});
}
render() {
const { fields: { email, password }, handleClick, submitting } = this.props
return (
<div>
<div className=
"fb-login-button"
data-max-rows="1"
data-size="medium"
data-show-faces="true"
data-auto-logout-link="true"
onclick={this.onClick}></div>
<div>{this.state.message}</div>
</div>
);
}
};
export default reduxForm({
form: 'FacebookButton',
fields: ['email','password'],
validate
},null,{facebookLogin})(FacebookButton)
and here is my login form where I render my facebook button
import React, { Component, PropTypes } from 'react';
import { reduxForm } from 'redux-form';
import { loginUser } from '../../actions/index';
import { Link } from 'react-router';
import googleLogin from './google_login.js';
import FacebookButton from './facebook_login.js';
function validate(values) {
const errors = {}
if (!values.email) {
errors.email = 'Required'
} else if (!/^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(values.email)) {
errors.email = 'Please enter a valid email address'
}
if (!values.password) {
errors.password = 'Required'
}
return errors
}
class LoginForm extends Component {
static contextTypes = {
router: PropTypes.object
};
onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail());
}
signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
onSubmit(props){
this.props.loginUser(props)
.then(() => {
this.context.router.push('/');
});
}
render() {
const { fields: { email, password }, handleSubmit, submitting } = this.props
return (
<div>
<form onSubmit={handleSubmit(this.props.loginUser)}>
<div className={`form-group ${email.touched && email.invalid ? 'has-danger' : ''}`}>
<label>E-mail</label>
<div>
{/* {email.touched && email.error && <div className={s.textError}>{email.error}</div>} */}
<input type="email" className="form-control" {...email}/>
<div className="email-help-login">
{email.touched ? email.error : ''}
</div>
</div>
</div>
<div className={`form-group ${password.touched && password.invalid ? 'has-danger' : ''}`}>
<label>Password</label>
<div>
{/* {password.touched && password.error && <div className={s.textError}>{password.error}</div>} */}
<input type="password" className="form-control" {...password}/>
<div className="password-help-login">
{password.touched ? password.error : ''}
</div>
</div>
</div>
<div>
<button type="submit" className="btn btn-primary">
Login
</button>
</div>
<div>
<Link to="/" className="btn btn-danger">Cancel</Link>
</div>
</form>
<FacebookButton fb={FB} />
<googleLogin/>
Sign out
</div>
)
}
}
export default reduxForm({
form: 'LoginForm',
fields: ['email','password'],
validate
},null,{loginUser})(LoginForm)
Here is my login page:
import React, { Component, PropTypes } from 'react';
import { reduxForm } from 'redux-form';
import { loginUser } from '../../actions/index';
import { Link } from 'react-router';
import { FACEBOOKLOGIN } from '../../constants/index';
import googleLogin from './google_login.js';
import FacebookButton from './facebook_login.js';
function validate(values) {
const errors = {}
if (!values.email) {
errors.email = 'Required'
} else if (!/^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(values.email)) {
errors.email = 'Please enter a valid email address'
}
if (!values.password) {
errors.password = 'Required'
}
return errors
}
class LoginForm extends Component {
static contextTypes = {
router: PropTypes.object
};
onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail());
}
signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
onSubmit(props){
this.props.loginUser(props)
.then(() => {
this.context.router.push('/');
});
}
render() {
const { fields: { email, password }, handleSubmit, submitting } = this.props
return (
<div>
<form onSubmit={handleSubmit(this.props.loginUser)}>
<div className={`form-group ${email.touched && email.invalid ? 'has-danger' : ''}`}>
<label>E-mail</label>
<div>
{/* {email.touched && email.error && <div className={s.textError}>{email.error}</div>} */}
<input type="email" className="form-control" {...email}/>
<div className="email-help-login">
{email.touched ? email.error : ''}
</div>
</div>
</div>
<div className={`form-group ${password.touched && password.invalid ? 'has-danger' : ''}`}>
<label>Password</label>
<div>
{/* {password.touched && password.error && <div className={s.textError}>{password.error}</div>} */}
<input type="password" className="form-control" {...password}/>
<div className="password-help-login">
{password.touched ? password.error : ''}
</div>
</div>
</div>
<div>
<button type="submit" className="btn btn-primary">
Login
</button>
</div>
<div>
<Link to="/" className="btn btn-danger">Cancel</Link>
</div>
</form>
<FacebookButton fb={FB} />
<googleLogin/>
Sign out
</div>
)
}
}
export default reduxForm({
form: 'LoginForm',
fields: ['email','password'],
validate
},null,{loginUser})(LoginForm)
Can anyone help me to solve this problem?
I'm assuming that FACEBOOKLOGIN isn't the default export in ../constants/index. Try this:
import { FACEBOOKLOGIN } from "../constants/index";
const API_URL = "http://localhost:3000";
//FACEBOOKLOGIN
export function facebookLogin(props){
const request = axios.post(`${API_URL}/users`,{
user: {
email:props.email,
password:props.password,
password_confirmation:props.password
}
});
return{
type: FACEBOOKLOGIN,
payload: request
}
}
UPDATE: With your new error message, the new problem has to do with this binding. React stops automatically binding this to all component methods a while back and now requires you to do that yourself. To fix this, change your FacebookButton constructor to this:
constructor(props) {
super(props);
this.FB = props.fb;
this.state = {
message: ""
};
this.onClick = this.onClick.bind(this);
}
I also see in the render method for FacebookButton that you're calling this.onClick. That's not what you want to do. Try this:
render() {
const { fields: { email, password }, handleClick, submitting } = this.props
return (
<div>
<div className=
"fb-login-button"
data-max-rows="1"
data-size="medium"
data-show-faces="true"
data-auto-logout-link="true"
onclick={this.onClick}></div>
<div>{this.state.message}</div>
</div>
);
}
UPDATE 2: Now it's telling you that FB is undefined. If FB is globally available (if you are getting the sdk through a script tag in your html), why not just use it that way instead of taking it as a prop? Ie. change this:
componentDidMount() {
FB.Event.subscribe('auth.logout',
this.onLogout.bind(this));
FB.Event.subscribe('auth.statusChange',
this.onStatusChange.bind(this));
}

Categories