【问题标题】:How to use react-redux to store a token and use it on multiple axios request?如何使用 react-redux 存储令牌并在多个 axios 请求中使用它?
【发布时间】:2018-04-28 09:36:13
【问题描述】:

我正在使用 react native 构建一个应用程序,该应用程序需要我使用令牌在同一个 API 上执行多个 get request。

假设网址是这样的

令牌 URL = https://test.co/v1/tokens,API URL 1 = https://test.co/v1/students 和 API URL 2 = https://test.co/v1/cars

首先,为了从任一 API URL 获取数据,我是这样写的

students_actions.js 的示例

import axios from 'axios';
import { FETCH_STUDENT } from './types';

const TOKEN_URL = '...'
const STUDENT_URL = '...'

export const fetchStudent = (callback) => async (dispatch) => {
    axios.post(TOKEN_URL, {
        email: 'email',
        password: 'password',
        role: 'user'
    })
    .then((response) => {
        const accessToken = response.data.token;
        //console.log(accessToken);
        axios.get(STUDENT_URL, {
            headers: { 'Authorization': 'Bearer '.concat(accessToken) }
        })
        .then((studentResponse) => {
            dispatch({ type: FETCH_STUDENT, payload: studentResponse.data });
            callback();
        })
        .catch((e) => {
            console.log(e);
        });
    })
    .catch((error) => {
        console.log(error);
    });
};

students_reducers.js 的示例

import { FETCH_STUDENT } from '../actions/types';

const INITIAL_STATE = {
    data: []
};

export default function (state = INITIAL_STATE, action) {
    switch (action.type) {
        case FETCH_STUDENT:
            return action.payload;
        default:
            return state;
    }
}

并像这样在渲染函数中调用它

//some code
import { connect } from 'react-redux';

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

onButtonPressProfile = () => {
    this.props.fetchStudent(() => {
        this.props.navigation.navigate('Profile');
    });
}
class StudentProfile extends Component {
    render() {
        return(
            <View><Text>{this.props.students.name}</Text></View>
        );
    }
}

function mapStateToProps({ students }) {
    return { students: students.data };
}

export default connect(mapStateToProps, actions)(StudentProfile);

虽然这一切都在正常运行,但我觉得 students_actions.js 可以通过编写用于在其他文件中检索令牌的代码并在 students_actions.js 中为 GET request 调用回值来进一步简化。

原因是我不必每次想访问students 或cars 时都请求令牌。可以说,我确实请求了一次,我可以使用相同的令牌 24 小时来访问 API。一旦过期,我必须再次请求令牌才能再次访问 API。

我已经为token_actions.js 和token_reducer.js 编写了代码。下面是两个代码。

token_actions.js

//import library
// this code works
const TOKEN_URL = apiConfig.url + 'tokens';
const auth = {
    email: 'email',
    password: 'password',
    role: 'user'
};

export const fetchToken = () => async (dispatch, getState) => {
        axios.post(TOKEN_URL, auth)
        .then((response) => {

            dispatch({ type: FETCH_TOKEN, payload: response.data.token });
        })
        .catch((error) => {
            console.log(error);
        });
};

token_reducer.js

import {
    FETCH_TOKEN
} from '../actions/types';

const INITIAL_STATE = {
    data: []
};

export default function (state = INITIAL_STATE, action) {
    switch (action.type) {
        case FETCH_TOKEN:
            return action.payload;
        default:
            return state;
}

}

students_actions.js

axios.get(STUDENT_URL, { headers: {
                           'Authorization': 'Bearer '.concat(here is the value from token_actions)}})

现在我被困在如何将有效负载从token_actions.js 调用/导入到students_actions.js 中?我应该使用mapStateToProps 还是有其他方法可以做到这一点?

目前,此应用还没有任何认证功能。它基本上是一个显示从 API 获取的数据的应用程序。

我主要根据我在网上找到的示例编写了这个应用程序,对于这个案例,我找到了这个example,但似乎并不是我真正想要实现的目标。

我不太了解 javascript,所以如果有人能指出与此案例相关的任何链接,或者 Stackoverflow 上的相同问题以及一些建议,我将非常高兴。

谢谢。

【问题讨论】:

    标签: javascript api react-native react-redux redux-thunk


    【解决方案1】:

    我要做的合乎逻辑的事情是创建类似 AuthReducer 的东西,您可以在其中存储令牌和刷新令牌。这是我的基本 AuthReducer 的示例:

    export const INITIAL_STATE = {
      oAuthToken: '',
      refreshToken: '',
    };
    
    export default AuthReducer = (state = INITIAL_STATE, action) => {
      switch (action.type) {
        case REFRESH_OAUTH_DATA:
          const { oAuthToken, refreshToken } = action.payload;
          return { ...state, oAuthToken, refreshToken };
    
        case LOGOUT:
          return INITIAL_STATE;
    
        case LOGIN_FETCH_SUCCESS:
          const { oAuthToken, refreshToken } = action.payload;
          return { ...state, oAuthToken, refreshToken };
    
        default:
          return state;
      }
    };
    

    现在您可以使用 getState 方法在您的操作中获取令牌:

    export const fetchStudent = (callback) => async (dispatch, getState) => {
        const token = getState().AuthReducer.oAuthToken;
        ....
    };
    

    请记住,如果您使用的是 ES6,您可能还想使用 await:

    export const fetchStudent = (callback) => async (dispatch, getState) => {
        try {
            const accessToken = getState().AuthReducer.oAuthToken;
    
            let response = await axios.get(STUDENT_URL, {
                headers: { 'Authorization': 'Bearer '.concat(accessToken) }
             })
    
             dispatch({ type: FETCH_STUDENT, payload: response.data });
             callback();
        } catch(e) {
            console.log(e);
        }
    };
    

    这样您的代码更易于阅读和维护。

    【讨论】:

    • 我应该如何导入AuthReducer?是不是像import { AuthReducer } from './AuthReducer'; 之上的students_actions.js?
    • 不,getState 方法是您的 redux 存储中的一个方法,由于 redux-thunk,它可以在您的操作中使用。您无需在操作中导入 reducer 即可访问它。
    • 我通常喜欢在顶层定义一个 API 文件夹,每个 API 功能都有自己的文件夹,并且在执行 fetch 所需的操作和一个 reducer 来保存请求的状态和结果.
    • 嗨,我尝试了你的基本AuthReducer 设置,eslint 给了我错误AuthReducer is not defined。我应该在哪里定义它?
    • 你是怎么导入的?还是在定义它的时候?
    猜你喜欢
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 2021-03-24
    • 2020-03-19
    • 2019-01-29
    • 2018-05-12
    相关资源
    最近更新 更多