Saja
Saja

Reputation: 183

Can't get createAsyncThunk to fire from connected React Component

I'm trying to use createAsyncThunk for some API calls but I can't seem to get it to work. My normal actions are working, so I must be connecting my component to redux correctly, but there's something different about createAsyncThunk I'm missing. Calling this.props.checkSession() from below does nothing. None of the console.logs inside checkSession are printed an fetch() never hits the server.

AppScreen

import React from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
import { connect } from 'react-redux';
import { checkSession } from './actions';
import { setToken } from './reducer';

class AppScreen extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    console.log("Mounted")
    this.props.checkSession();
    console.log("Moving on")
    if (!this.props.loading && !this.props.auth_token) {
      this.props.navigation.navigate('Auth')
    }
  }

  render() {
    if (this.props.loading) {
      return (
        <View style={{ flex: 1 }}>
          <ActivityIndicator />
        </View>
      )
    } else {
      return (
        <View>
          <Text>You're in! {this.props.auth_token}</Text>
        </View>
      )
    }
  }
}

function mapStateToProps(state) {
  return {
    user: state.app.user,
    auth_token: state.app.auth_token,
    loading: state.app.loading,
    error: state.app.error
  };
}

const mapDispatchToProps = dispatch => {
  return {
    checkSession: () => dispatch(checkSession),
    setToken: token => dispatch(setToken(token))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(AppScreen);

Actions

import { createAsyncThunk } from "@reduxjs/toolkit";
import { API_URL, ENDPOINTS } from "./../constants";

export const checkSession = createAsyncThunk("checkSession", (thunkAPI) => {
  console.log("Running")
  let body = {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({auth_token: thunkAPI.getState().app.auth_token})
  }

  console.log("Checking session.")

  return fetch(`${API_URL}${ENDPOINTS.CHECK_SESSION}`, body)
    .then(response => {
      console.log(`API hit: ${response.ok}`)
      if (!response.ok) throw Error(response.statusText);
      return response.json();
    })
    .then(json => json);
});

Reducer

import { createSlice } from "@reduxjs/toolkit";

import { checkSession } from "./actions"

const appSlice = createSlice({
  name: "app",
  initialState: {
    loading: true,
    auth_token: "",
    error: "",
    user: {}
  },
  reducers: {
    setToken: (state, action) => {
      state.auth_token = action.payload;
      state.loading = false;
    },
  },
  extraReducers: {
    [checkSession.pending]: state => {
      state.loading = true;
    },
    [checkSession.rejected]: (state, action) => {
      state.loading = false;
      state.error = action.error.message;
    },
    [checkSession.fulfilled]: (state, action) => {
      state.loading = false;
      state.user = action.payload.user;
      state.auth_token = action.payload.auth_token;
    }
  }
});

export const { setToken } = appSlice.actions;
export const appReducer = appSlice.reducer;

Store

import { appReducer } from "./App/reducer";
import { authReducer } from "./Auth/reducer";
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";

const middleware = [
  ...getDefaultMiddleware(),
]

const store = configureStore({
  reducer: {
    app: appReducer,
    auth: authReducer
  },
  middleware,
});

export default store;

Upvotes: 1

Views: 829

Answers (1)

markerikson
markerikson

Reputation: 67577

You're using checkSession wrong. It should be dispatch(checkSession()).

That said, you should also be using the "object shorthand" form of mapDispatch, like this:

const mapDispatch = {checkSession, setToken};

Upvotes: 2

Related Questions