Maykel
Maykel

Reputation: 175

dispatching action in redux-saga is not fetching data

I am studying redux-saga and I want to fetch data from :

https://jsonplaceholder.typicode.com/posts

and in my redux folder I have the fallowing:

(it can be checked in this github repository https://github.com/jotasenator/redux-saga-fetching-example/tree/main/src)

\src\redux\api.js

import axios from 'axios'

export const loadPostApi = async () => {
    await axios.get(`https://jsonplaceholder.typicode.com/posts`)
}

the get request to the address in question

src\redux\app.actions.js

export const loadPostStart = () => ({
    type: 'LOAD_POST_START',

})
export const loadPostSuccess = (posts) => ({
    type: 'LOAD_POST_SUCCESS',
    payload: posts,
})
export const loadPostFail = (error) => ({
    type: 'LOAD_POST_FAIL',
    payload: error,
})

those are the actions functions

src\redux\app.reducer.js

const INITIAL_STATE = {
    loading: false,
    posts: [],
    errors: null,
}

export const appReducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case 'LOAD_POST_START':
            return {
                ...state,
                loading: true,
            }
        case 'LOAD_POST_SUCCESS':
            return {
                ...state,
                posts: action.payload,
                loading: false,
            }
        case 'LOAD_POST_FAIL':
            return {
                ...state,
                errors: action.payload,
                loading: false,
            }

        default:
            return state;
    }
}

the reducer of the fetching, updating state,

src\redux\counterReducer.js

import { types } from "./types";

const initialState = {
    value: 0
}

export const counterReducer = (state = initialState, action) => {
    switch (action.type) {
        case types.adicionar:
            return {
                ...state,
                value: state.value + 1
            }

        case types.resetear:
            return {
                ...state,
                value: 0
            }

        case types.restar:
            return {
                ...state,
                value: state.value - 1
            }

        default:
            return state
    }
}

this is the reducer of the counter app, with different approach, types are isolated in another file

src\redux\rootReducer.js

import { combineReducers } from 'redux'
import { counterReducer } from './counterReducer'
import { appReducer } from './app.reducer'

export const rootReducer = combineReducers({
    counterReducer,
    appReducer
})

the rootReducer for gathering the reducers

src\redux\sagas.js

import { put, takeLatest, call } from 'redux-saga/effects'
import { loadPostApi } from './api'
import { loadPostFail, loadPostSuccess } from './app.actions'

export function* onLoadPostStartAsync() {
    try {
        const response = yield call(loadPostApi)
        yield put(loadPostSuccess(response.data))
    } catch (error) {
        yield put(loadPostFail(error))

    }
}

export function* onLoadPost() {
    yield takeLatest('LOAD_POST_START', onLoadPostStartAsync)

}

export default function* rootSaga() {
    yield ([
        onLoadPost(),
    ])
}

saga onLoadPostStartAsync called by saga onLoadPost inside rootSaga

src\redux\store.js

import { applyMiddleware, compose, createStore } from "redux";
import createSagaMiddleware from 'redux-saga'

import { rootReducer } from "./rootReducer";

import rootSaga from "./sagas";

const sagaMiddleware = createSagaMiddleware()

const composeEnhancers = (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose

const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware))

export const store = createStore(rootReducer, enhancer)

sagaMiddleware.run(rootSaga)

this is the store with the redux_devtool_extension, the reducers, and running rootSaga

src\redux\types.js

export const types = {
    adicionar: 'ADICIONAR',
    resetear: 'RESETEAR',
    restar: 'RESTAR'
}

those are the types of the counterApp reducer

src\Counter.js

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'

export const Counter = () => {

  const dispatch = useDispatch()
  const { value } = useSelector(state => state.counterReducer)

  const handleAdicionar = () => {
    dispatch({ type: 'ADICIONAR' })
  }
  const handleResetear = () => {
    (value !== 0) && dispatch({ type: 'RESETEAR' })
  }
  const handleRestar = () => {
    dispatch({ type: 'RESTAR' })
  }
  console.log(value)
  return (
    <div>
      <button onClick={handleAdicionar}>Adicionar</button>
      {' '}
      <button onClick={handleResetear}>Resetear</button>
      {' '}
      <button onClick={handleRestar}>Restar</button>
      <hr />

    </div>
  )
}

this is the Counter component, it works ok

src\Fetching.js

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { loadPostStart } from './redux/app.actions'


export const Fetching = () => {
    const dispatch = useDispatch()

    const fetchPost = () => {
        dispatch(loadPostStart())
    }

    const state = useSelector(state => state.appReducer)
    console.log(state)


    return (
        <>
            <h1>Fetching from https://jsonplaceholder.typicode.com</h1>
            <button onClick={fetchPost}>Fetching</button>
            {
                !state.loading && state.posts.map((post) => (
                    <li key={post.id}><h2>{post.title}</h2></li>

                ))
            }

        </>
    )
}

the Fetching component click on the button calls fetchPost function who dispatch loadPostStart() function which is the same of dispatching {type: 'LOAD_POST_START'}, but nothing happens here when clicking, not fetch nothing from here https://jsonplaceholder.typicode.com/posts

src\index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { store } from './redux/store';
import { Provider } from "react-redux";
import { Unificator } from './Unificator';

ReactDOM.render(
  <Provider store={store}>
    <Unificator />
  </Provider>,


  document.getElementById('root')
);

component Unificator has Counter and Fetching component

src\Unificator.js

import React from 'react'
import { Counter } from './Counter'
import { Fetching } from './Fetching'

export const Unificator = () => {
    return (
        <div>
            <Counter />
            <Fetching />

        </div>
    )
}


as you can see is about of two reducers, one is the famous counter, and the another one is the fetching issue, do not know what is happening that is not fetching the data

obviously, i am doing something wrong here...don t see where

Upvotes: 0

Views: 1104

Answers (1)

Mahadev Bk
Mahadev Bk

Reputation: 524

Axio returns promise, You need to capture that and return. Please try replacing below code.


export const loadPostApi = async () => {
    await axios.get(`https://jsonplaceholder.typicode.com/posts`)
    .then((response) => {
         console.log('Response', response);
         return response;
    })
    .catch((error) => {
         console.log('error', error);
    })
}

Upvotes: 0

Related Questions