Skip to content

Instantly share code, notes, and snippets.

@mvalipour
Created November 7, 2016 23:10
Show Gist options
  • Select an option

  • Save mvalipour/1fc8a506dd1d49a20b675e08130b105d to your computer and use it in GitHub Desktop.

Select an option

Save mvalipour/1fc8a506dd1d49a20b675e08130b105d to your computer and use it in GitHub Desktop.
Login form in React

using:

  • react-router
  • react-router-redux
  • react-act
// reducers.js

import { createAction, createReducer } from 'redux-act';
import { push } from 'react-router-redux'

// storage
// TEMP: using local storage
const USER_STORAGE_KEY = '@auth/user';
const storeUser = user => localStorage.setItem(USER_STORAGE_KEY, !!user ? JSON.stringify(user) : null);
const loadUser = () => JSON.parse(localStorage.getItem(USER_STORAGE_KEY));

// initial state
const getInitialState = () => {
  const user = loadUser();
  return { loggedIn: !!user, user };
};

// private actions
const loginInProgress = createAction('login in progress');
const loginSuccessful = createAction('login successfull');
const logoutSuccessful = createAction('logged out');

// public actions
export const login = (returnTo) => dispatch => {
  dispatch(loginInProgress());

  new Promise(() => {
    setTimeout(() => {
      const user = { name: 'Mo' };
      storeUser(user);

      dispatch(loginSuccessful(user));
      dispatch(push(returnTo));
    }, 1000);
  });
};

export const logout = () => dispatch => {
  storeUser(null);
  dispatch(logoutSuccessful());
  dispatch(push('/'));
};

// reducers
export default createReducer({
  [loginInProgress] : (state) => ({ ...state, inProgress: true }),
  [loginSuccessful] : (state, user) => ({ loggedIn: true, user }),
  [logoutSuccessful] : (state) => ({ })
}, getInitialState());
// some.js
// setup/index.js

// ...
const middleware = applyMiddleware(
  thunk,
  routerMiddleware(browserHistory)
);
const store = createStore(reducers, middleware);
const history = syncHistoryWithStore(browserHistory, store);
// ...
// container/login/index.js

import React, { Component } from 'react';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

import * as actions from '../../act/auth';

class Login extends Component {
  render() {
    const { location, actions, inProgress } = this.props;
    const { returnTo } = location.query;

    const handleLoginClick = () => {
      actions.login(returnTo);
    }

    const button = !inProgress ?
      (<button onClick={handleLoginClick}>click here to login</button>) :
      'in progress...';

    return (<div>
      <p>this is login. you will be redirected to: <b>{returnTo}</b></p>
      <div>{button}</div>
    </div>);
  }
}

const mapStateToProps = state => ({ ...state.auth });
const mapDispatchToProps = dispatch  => ({ actions: bindActionCreators(actions, dispatch) });

export default connect(mapStateToProps, mapDispatchToProps)(Login);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment