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

How do you delay an async thunk action until after authentication session token has been stored?

我已经构建了一个 API,我正在尝试获取数据(使用 axios)并将其呈现到我的 react-native 应用程序(node/express 服务器)中的一个组件中。我正在使用 JWT 来验证我的用户和屏幕路由的反应导航。

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

中的数据列表

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

执行应该是-

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

啊啊!我想不通。请帮忙? :(

我尝试调用生命周期方法 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);
        };
    };
};

这是我的 activity 列表缩减器 -

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;
    }
 };

这是我的 authentication/login thunk 动作创建者 -

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);
        };
   };
 };

这是我的 login/auth reducer -

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 在保存令牌之前正在调用!

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

哇...我弄清楚我做错了什么,我觉得很可笑,因为我没有早点意识到 x_x 我忘了在 GET 请求中添加 auth header,这就是为什么它不是正在验证。

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

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

对于以后阅读本文的任何人 ----- 请确保您添加了您的身份验证 header。感谢@Oblosys 的回复,这让我意识到它与保存令牌的时间无关。