2017-12-14 9 views
0

私のReact/Reduxアプリケーションでは、ユーザーが間違った資格で「ログイン」しようとすると、私の約束を作成しました。しかし、私がAuth.jsファイルの 'login'関数のreturn文を 'error'の代わりに 'response'のような未定義の変数に変更すると、本当にエラーが発生し、それが私のレデューサーに登録されます。他の投稿を見て、私はそれを理解することができませんでした。私はこのロジック、Auth、Sagas、Reducersを扱う3つのファイルを持っています。すべてのヘルプは感謝React/Redux reducerは約束のエラーを登録しません

Auth.js

import axios from 'axios'; 
import cookie from 'react-cookie'; 

export const API_URL = 'http://13.59.102.50:8000'; 

const transformRequest = (obj) => { 
    let str = []; 
    for (let p in obj) { 
    str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p])); 
    } 
    return str.join('&'); 
}; 

const auth = { 
    /** 
    * Logs a user in returning a promise with 'true' when done 
    */ 
    login(email, password) { 
    // if already logged in return promise 
    if (auth.loggedIn()) { 
     return Promise.resolve(true); 
    } 
    console.log('in login'); 
    const data = { 
     email, 
     password, 
    }; 
    const url = API_URL + '/tokens'; 
    // post request 
    return axios.post(url, transformRequest(data)) 
     .then(response => { 
     cookie.save('token', response.data.token, { path: '/' }); 
     cookie.save('email', response.data.user.email, { path: '/' }); 

     return response.data; 
     }) 
     .catch((error) => { 
      console.log(error, 'This is an error') 
     }); 
    }, 
    /** 
    * Logs the user out 
    */ 
    logout() { 
    cookie.remove('token', { path: '/' }); 
    cookie.remove('email', { path: '/' }); 
    return Promise.resolve(true); 
    }, 

    /** 
    * 
    * Checks if user is logged in 
    */ 
    loggedIn() { 
    return !!cookie.load('token'); 
    }, 

    /** 
    * 
    * Get user information 
    */ 
    getUserInfo() { 
    const email = cookie.load('email'); 
    const token = cookie.load('token'); 
    const url = API_URL + `/users/${email}`; 
    const config = { 
     headers: { 'Authorization': `Bearer ${token}` }, 
    }; 
    // post request 
    return axios.get(url, config) 
     .then(response => { 
     return { user: response.data }; 
     }) 
     .catch((error) => { 
     console.log(error.response); 
     }); 


    return !!cookie.load('token'); 
    }, 

    /** 
    * Registers a user then logs them in 
    **/ 
    register(name, email, password, account_type) { 
    const data = { 
     name, 
     email, 
     password, 
     account_type 
    }; 

    const url = API_URL + '/users'; 
    return axios.post(url, transformRequest(data)) 
     .then(response => { 
     console.log('response:' + response); 
     return response.data; 
     }) 
     .catch((error) => { 
     console.log(error.response); 
     }); 
    }, 
}; 

export default auth; 

Sagas.js

// This file contains the sagas used for async actions in our app. It's divided into 
// "effects" that the sagas call (`authorize` and `logout`) and the actual sagas themselves, 
// which listen for actions. 

// Sagas help us gather all our side effects (network requests in this case) in one place 

import { take, call, put, race } from 'redux-saga/effects'; 
import { browserHistory } from 'react-router'; 

import auth from 'utils/auth'; 
import { toastr } from 'lib/react-redux-toastr'; 

import { 
    SENDING_REQUEST, 
    LOGIN_REQUEST, 
    REGISTER_REQUEST, 
    SET_AUTH, 
    LOGOUT, 
    FETCH_USER, 
    CHANGE_FORM, 
    REQUEST_ERROR, 
    SET_USER, 
    CLEAR_USER, 
} from './constants'; 

/** 
* Effect to handle authorization 
* @param {string} email     The email of the user 
* @param {string} password    The password of the user 
* @param {object} options    Options 
* @param {boolean} options.isRegistering Is this a register request? 
*/ 
export function* authorize({ name, email, password, accountType, isRegistering }) { 
    // We send an action that tells Redux we're sending a request 
    yield put({ type: SENDING_REQUEST, sending: true }); 

    // We then try to register or log in the user, depending on the request 
    try { 
    // let salt = genSalt(email); 
    // let hash = hashSync(password, salt); 
    let response; 

    // For either log in or registering, we call the proper function in the `auth` 
    // module, which is asynchronous. Because we're using generators, we can work 
    // as if it's synchronous because we pause execution until the call is done 
    // with `yield`! 
    if (isRegistering) { 
     response = yield call(auth.register, name, email, password, accountType); 
    } else { 
     response = yield call(auth.login, email, password); 
    } 
    return response; 
    console.log(response,'This is a big response') 
    } catch (error) { 
    console.log('hi'); 
    // If we get an error we send Redux the appropiate action and return 
    yield put({ type: REQUEST_ERROR, error: error.message }); 

    return false; 
    } finally { 
    // When done, we tell Redux we're not in the middle of a request any more 
    yield put({ type: SENDING_REQUEST, sending: false }); 
    } 
} 

/** 
* Effect to handle logging out 
*/ 
export function* logout() { 
    // We tell Redux we're in the middle of a request 
    yield put({ type: SENDING_REQUEST, sending: true }); 

    // Similar to above, we try to log out by calling the `logout` function in the 
    // `auth` module. If we get an error, we send an appropriate action. If we don't, 
    // we return the response. 
    try { 
    const response = yield call(auth.logout); 
    yield put({ type: SENDING_REQUEST, sending: false }); 
    return response; 
    } catch (error) { 
    yield put({ type: REQUEST_ERROR, error: error.message }); 
    return error.message; 
    } 
} 

/** 
* Log in saga 
*/ 
export function* loginFlow() { 
    // Because sagas are generators, doing `while (true)` doesn't block our program 
    // Basically here we say "this saga is always listening for actions" 
    while (true) { 
    // And we're listening for `LOGIN_REQUEST` actions and destructuring its payload 
    const request = yield take(LOGIN_REQUEST); 
    const { email, password } = request.data; 

    // A `LOGOUT` action may happen while the `authorize` effect is going on, which may 
    // lead to a race condition. This is unlikely, but just in case, we call `race` which 
    // returns the "winner", i.e. the one that finished first 
    const winner = yield race({ 
     auth: call(authorize, { email, password, isRegistering: false }), 
     logout: take(LOGOUT), 
    }); 
    // If `authorize` was the winner... 
    if (winner.auth) { 
     // ...we send Redux appropiate actions 
     yield put({ type: SET_AUTH, newAuthState: true }); // User is logged in (authorized) 
     yield put({ type: SET_USER, user: winner.auth }); 
     yield put({ type: CHANGE_FORM, newFormState: { email: '', password: '' } }); // Clear form 
     yield call(forwardTo, '/'); // Go to dashboard page 
     // If `logout` won... 
    } else if (winner.logout) { 
     // ...we send Redux appropiate action 
     yield put({ type: SET_AUTH, newAuthState: false }); // User is not logged in (not authorized) 
     yield call(logout); // Call `logout` effect 
     yield call(forwardTo, '/login'); // Go to root page 
    } 
    } 
} 

/** 
* Log out saga 
* This is basically the same as the `if (winner.logout)` of above, just written 
* as a saga that is always listening to `LOGOUT` actions 
*/ 
export function* logoutFlow() { 
    while (true) { 
    yield take(LOGOUT); 
    yield put({ type: SET_AUTH, newAuthState: false }); 

    yield call(logout); 
    yield put({ type: CLEAR_USER }); 

    yield call(forwardTo, '/login'); 

    toastr.success('Success!', 'You are now logged out.'); 
    } 
} 

/** 
* Get user information saga 
*/ 
export function* getUserFlow() { 
    while (true) { 
    yield take(FETCH_USER); 
    try { 
     const response = yield call(auth.getUserInfo); 
     yield put({ type: SET_USER, user: response }); 
    } catch (error) { 
     yield put({ type: REQUEST_ERROR, error: error.message }); 
     return error.message; 
    } 
    } 
} 

/** 
* Register saga 
* Very similar to log in saga! 
*/ 
export function* registerFlow() { 
    while (true) { 
    // We always listen to `REGISTER_REQUEST` actions 
    const request = yield take(REGISTER_REQUEST); 
    const { name, email, password, accountType } = request.data; 
    // We call the `authorize` task with the data, telling it that we are registering a user 
    // This returns `true` if the registering was successful, `false` if not 
    const wasSuccessful = yield call(authorize, {name, email, password, accountType, isRegistering: true }); 

    // If we could register a user, we send the appropriate actions 
    if (wasSuccessful) { 
     yield put({ type: SET_AUTH, newAuthState: true }); // User is logged in (authorized) after being registered 
     yield put({ type: CHANGE_FORM, newFormState: { name: '', password: '' } }); // Clear form 
     yield put({ type: LOGIN_REQUEST, data: { email, password } }); 
     forwardTo('/dashboard'); // Go to dashboard page 
    } 
    } 
} 

// The root saga is what we actually send to Redux's middleware. In here we fork 
// each saga so that they are all "active" and listening. 
// Sagas are fired once at the start of an app and can be thought of as processes running 
// in the background, watching actions dispatched to the store. 
export default [ 
    loginFlow, 
    logoutFlow, 
    registerFlow, 
    getUserFlow, 
]; 

// Little helper function to abstract going to different pages 
export function* forwardTo(location) { 
    yield call(browserHistory.push, location); 
} 

を高く評価しているReducer.js

/* 
* The reducer takes care of state changes in our app through actions 
*/ 
import { fromJS } from 'immutable'; 
import auth from 'utils/auth'; 
import { 
    CHANGE_FORM, 
    SET_AUTH, 
    SENDING_REQUEST, 
    REQUEST_ERROR, 
    CLEAR_ERROR, 
    SET_USER, 
    CLEAR_USER, 

} from './constants'; 


// The initial application state 
const initialState = fromJS({ 
    formState: { 
    email: '', 
    password: '', 
    }, 
    error: '', 
    currentlySending: false, 
    user: {}, 
    loggedIn: auth.loggedIn(), 
}); 

// Takes care of changing the application state 
function globalReducer(state = initialState, action) { 
    switch (action.type) { 
    case CHANGE_FORM: 
    return state.set('formState', action.newFormState); 
    case SET_AUTH: 
    return state.set('loggedIn', action.newAuthState); 
    case SET_USER: 
    return state.set('user', action.user.user); 
    case SENDING_REQUEST: 
    return state.set('currentlySending', action.sending); 
    case REQUEST_ERROR: 
    return state.set('error', action.error); 
    case CLEAR_ERROR: 
    return state.set('error', ''); 
    case CLEAR_USER: 
    return state.set('user', {}); 
    default: 
    return state; 
    } 
} 

export default globalReducer; 

答えて

1

ヨあなたはエラーを投げる必要があります:

return axios.post(url, transformRequest(data)) 
     .then(response => { 
     cookie.save('token', response.data.token, { path: '/' }); 
     cookie.save('email', response.data.user.email, { path: '/' }); 

     return response.data; 
     }) 
     .catch((error) => { 
      throw error; 
     }); 
関連する問題