SGhaleb
SGhaleb

Reputation: 1007

Redux saga not calling the API

I am trying to use redux-saga to call my API and passing it a parameter. I am using redux-logger and console.log() to debug. But it seems that my saga doesn't go call the API for some reason.

Here is the console log of the states... as you can see the apiMsg doesnt change, however I have it change for each action.

enter image description here

I think I am going wrong somewhere in the actions, reducer or the component. Or else I am calling the API wrong in the Saga.

This is my code

api.js

import axios from 'axios';

export function getPostApi(postId){
  return axios.get(
    `https://jsonplaceholder.typicode.com/posts/${postId}`
  ).then(
    response => {
      return response;
    }
  ).catch(
    err => {throw err;}
  );
}

my store

import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga'
import {createLogger} from 'redux-logger';
import rootReducer from '../Reducers';

export default function configureStore(initialState) {
  const sagaMiddleware = createSagaMiddleware();
  const logger = createLogger();
  return {
    ...createStore(rootReducer, initialState, applyMiddleware(sagaMiddleware, logger)),
    runSaga: sagaMiddleware.run
  }
}

the saga

import {call, put, takeEvery} from 'redux-saga/effects';
import * as service from '../Services/api';
import * as actions from '../Actions';
import * as types from '../actions/actionTypes';

export function* fetchPost(action){
  try{
    yield put(actions.apiRequest());
    const [post] = yield [call(service.getPostApi, action.postId)];
    yield put(actions.apiRequestSucceeded(post));
  } catch(e){
    yield put(actions.apiRequestFailed());
  }
}

export function* watchApiRequest() {
  yield takeEvery(types.FETCH_POST, fetchPost);
}

actions

import * as types from './actionTypes';

export const fetchPost = (postId) => ({
  type: types.FETCH_POST,
  postId,
});

export const apiRequest = () => {
  return {
    type: types.API_REQUEST
  }
}

export const apiRequestSucceeded = (post) => {
  return {
    type: types.API_REQUEST_SUCCEEDED,
    post
  }
}

export const apiRequestFailed = () => {
  return {
    type: types.API_REQUEST_FAILED
  }
}

reducer

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

const initialState = {
  apiMsg: '',
  postId: 1,
  fetching: false,
  post: null
};

export default function getPostData(state = initialState, action) {
  switch (action.type) {
    case types.API_REQUEST:
      return {
        ...state,
        apiMsg: 'API call request!',
        fetching: true
      }
    case types.API_REQUEST_SUCCEEDED:
      return {
        ...state,
        apiMsg: 'API called succeeded!',     
        fetching: false,
        postId: action.post.id,
        post: action.title
      };
    case types.API_REQUEST_FAILED:
      return {
        ...state,
        apiMsg: 'API called failed!',
        fetching: false,
      };
    default:
      return state;
  }
}

the component page

import React, { Component } from 'react';
import { View, Text} from 'react-native';
import { connect } from 'react-redux';
import {fetchPost} from './Actions/apiTesterActions';

class TestPage extends Component {
  constructor() {
    super();
  }

  componentDidMount() {
    this.props.fetchPost(1)
  }

   render() {
    const { postId, fetching, post } = this.props;
    console.log('Test page props', postId, fetching, post);
    return (
      <View> 
        <Text>Test Page Works! </Text>
      </View>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    postId: state.getPostData.postId,
    fetching: state.getPostData.fetching,
    post: state.getPostData.post
  }
};

export default connect(mapStateToProps, {fetchPost})(TestPage);

I am still learning Redux, and now redux-saga, so I don't fully understand the structure/hierarchy, but I am learning and any advice is helpful. Thank you

EDIT: I am using this redux saga api call example as a guide.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import configureStore from './ReduxTest/Store/configureStore';
import rootSaga from './ReduxTest/sagas';

const store = configureStore();
store.runSaga(rootSaga)

ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
registerServiceWorker();

saga/index.js

import {fork, all} from 'redux-saga/effects';
import {watchApiRequest} from './apiTester';

export default function* rootSaga() {
  yield all [
    fork(watchApiRequest)
  ]
}

Upvotes: 4

Views: 4611

Answers (1)

SGhaleb
SGhaleb

Reputation: 1007

After some time with a lot of debugging, I have figured the problem.

When I first started creating the application, I got the following error...

[...effects] has been deprecated in favor of all([...effects]), please update your code

As the yield all [...] was deprecated, I changed my code without taking it into consideration, I was happy the error went, but didn't realize how much of an impact it would have on my application.

(wrong) saga/index.js

import {fork, all} from 'redux-saga/effects';
import {watchApiRequest} from './apiTester';

export default function* rootSaga() {
  yield all [
    fork(watchApiRequest)
  ]
}

(right) saga/index.js

import {fork, all} from 'redux-saga/effects';
import {watchApiRequest} from './apiTester';

export default function* rootSaga() {
  yield all ([
    fork(watchApiRequest)
  ])
}

As You can see it needed to be wrapped in brackets yield all ([...]) You will get the deprecated error but your code will still work. I am unsure how to fix the deprecated error.

If someone knows how to get rid of the deprecated error than that would great.

Upvotes: 2

Related Questions