如何在存储身份验证会话令牌之前延迟异步thunk操作?

时间:2018-04-15 21:32:49

标签: reactjs react-native redux jwt redux-thunk

我已经构建了一个API,我试图获取数据(使用axios)并将其渲染到我的react-native app(节点/快速服务器)中的组件中。我使用JWT对我的用户进行身份验证,并使用反应导航进行屏幕路由。

我成功验证会话令牌并将其存储到AsyncStorage中。登录后,应用程序会导航到第一个屏幕,我想在其中显示来自API的数据列表。

问题是在将令牌保存到AsyncStorage之前正在执行GET请求,因此我收到了401未经授权的错误。

执行应该是 -

1)验证用户 2)使用获取的数据渲染组件

AHH!我无法弄明白。请帮忙? :(

我尝试在生命周期方法componentDidMount中调用该操作,但没有成功。

这里是父组件:

class PlansScreen extends Component {

static navigationOptions = ({ navigation }) => ({
    tabBarLabel: 'Plans',
    tabBarIcon: ({ tintColor }) => (
        <Icon name="schedule" size={30} color={tintColor} />
    )
});

render() {
    return (
        <View>
            <ActivityList/>
        </View>
    );
  }
}

export default PlansScreen;

这里是我想要呈现获取数据列表的子组件: 忽略了我尚未充实整个组件这一事实,我目前正试图在会话令牌保存后执行API请求

class ActivityList extends Component {

componentDidMount() {
    this.props.fetchActivities();
}


render() {
    // console.log(this.props);
    return (
        <View>
            <FlatList 
            //My data will render here
            />
        </View>
    );
  }
}

export default connect(null, { 
fetchActivities, 
})(ActivityList);

这是fetchActivities thunk动作创建者 -

export const fetchActivities = () => {
return async (dispatch) => {
    try {
        dispatch({ type: FETCH_ACTIVITIES_INITIATE });

        let token = await AsyncStorage.getItem('token');

        let { data } = await axios.get(`${ROOT_URL}/activities`);

            dispatch({ 
                type: FETCH_ACTIVITIES_SUCCESS,
                payload: data
            });            


            console.log(data);

    } catch(error) { 
            if (error.response) {
                console.log(error.response.data);
                console.log(error.response.status);
                console.log(error.response.headers);
            } else if (error.request) {
                console.log(error.request);
            } else {
                console.log('Error', error.message);
            }
            console.log(error.config);
            // signupUserFail(dispatch);
        };
    };
};

这是我的活动列表缩减器 -

import {
   FETCH_ACTIVITIES_INITIATE,
   FETCH_ACTIVITIES_SUCCESS
} from '../actions/types';

const INITIAL_STATE = {
   activities: null,
   loading: false
 };

export default (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case FETCH_ACTIVITIES_INITIATE:
            return { ...state, loading: true };

        case FETCH_ACTIVITIES_SUCCESS:
            return {...state,
                   activities: action.payload,
                   loading: false
                   };        
        default:
            return state;
    }
 };

这是我的身份验证/登录thunk action creator -

export const loginUser = ({ userEmail, userPassword, navigation }) => {

return async (dispatch) => {
    try {
        dispatch({ type: LOGIN_USER_INITIATE });

        let { data } = await axios.post(`${ROOT_URL}/users/login`, {
            userEmail, userPassword
        });

        AsyncStorage.setItem('token', data.token);
        // AsyncStorage.getItem('token').then((res) => console.log(res));

            dispatch({ 
                type: LOGIN_USER_SUCCESS,
                payload: data
            });            


            navigation.navigate('Plans');

            console.log(data);
            // console.log(store.getState());

    } catch(error) { 
            if (error.response) {
                console.log(error.response.data);
                console.log(error.response.status);
                console.log(error.response.headers);
            } else if (error.request) {
                console.log(error.request);
            } else {
                console.log('Error', error.message);
            }
            // console.log(error.config);
            loginUserFail(dispatch);
        };
   };
 };

这是我的登录/身份验证减速机 -

const INITIAL_STATE = { 
   userName: '',
   userEmail: '',
   userPassword: '',
   user: null,
   loginError: '',
   signupError: '',
   loading: false
};

export default (state = INITIAL_STATE, action) => {
    // console.log(action);
    switch (action.type) {
        case USERNAME_CHANGED:
            return {...state, userName: action.payload};

        case EMAIL_CHANGED:
            return {...state, userEmail: action.payload};

        case PASSWORD_CHANGED:
            return {...state, userPassword: action.payload};

        case LOGIN_USER_INITIATE:
            return {...state, loading: true, loginError: '', signupError: ''};

        case SIGNUP_USER_INITIATE:
            return {...state, loading: true, loginError: '', signupError: ''};

        case LOGIN_USER_SUCCESS:
            return { ...state, 
                user: action.payload, 
                loginError: '', 
                signupError: '', 
                loading: false,
                userPassword: '',
                userEmail: ''
            };

        case LOGIN_USER_FAIL:
            return { ...state, loginError: 'Authentication failed!', userPassword: '', loading: false };

        case SIGNUP_USER_FAIL:
            return { ...state, signupError: 'Signup failed!', userPassword: '', loading: false };

        default: 
            return state;
   }
};

在保存令牌之前调用this.props.fetchActivities!

我一直在努力解决这个问题!非常感谢任何帮助,即使只是为了引导我朝着正确的方向前进。

1 个答案:

答案 0 :(得分:0)

哇...我弄清楚我做错了什么,我觉得很快就没有意识到x_x我忘了将auth标头添加到GET请求中,这就是为什么它没有进行身份验证。

在fetchActivities动作创建者中,对我来说应该是 -

let { data } = await axios.get(`${ROOT_URL}/activities`, { 
    headers: { 'x-auth': `${token}` } 
});

对于将来阅读此内容的任何人-----请确保添加了您的身份验证标头。感谢@Oblosys的回复,这让我意识到它与令牌保存时没有任何关系。