如何使用 react-redux 存储令牌并在多个 axios 请求中使用它?

Posted

技术标签:

【中文标题】如何使用 react-redux 存储令牌并在多个 axios 请求中使用它?【英文标题】:How to use react-redux to store a token and use it on multiple axios request? 【发布时间】: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 调用回值来进一步简化。

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

我已经为token_actions.jstoken_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,所以如果有人能指出与此案例相关的任何链接,或者 *** 上的相同问题以及一些建议,我将非常高兴。

谢谢。

【问题讨论】:

【参考方案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。我应该在哪里定义它? 你是怎么导入的?还是在定义它的时候?

以上是关于如何使用 react-redux 存储令牌并在多个 axios 请求中使用它?的主要内容,如果未能解决你的问题,请参考以下文章

React-Redux操作未被触发

为啥不将 JWT 访问令牌存储在内存中并在 cookie 中刷新令牌?

将 JWT 令牌存储在共享首选项中?并在整个应用程序中检索价值?

localstorage 在页面刷新时在 react-redux 应用程序中返回“未定义”

gdata OAuth2如何使用多个用户的令牌

如何在 MySQL 和 PHP 中存储和使用 OAuth 令牌?