Search code examples
reactjsreduxreact-reduxredux-thunk

Manipulating Redux output


I'm working on a React application to render content of a WordPress website using the WordPress Rest API, Redux and Thunk.

The WordPress API returns posts without detailed information about the category (name, slug, etc). All I'm getting is the id. I'm currently calling an additional action/function to get the detailed category information (output). Below an example of how I'm currently fetching my posts.

// Actions.js

import axios from 'axios'

export const fetchPosts = (page = 1) => {
  return {
    type: "FETCH_POSTS",
    payload: axios.get(`${REST_URL}/wp/v2/posts?per_page=14&page=${page}`)
  }
}

|

// PostsReducer.js
const initialState = {
  posts: [],
  fetching: false,
  fetched: false,
  error: null
}

export default function reducer(state=initialState, action) {
  switch (action.type) {
    case "FETCH_POSTS": {
      return {
        ...state, 
        fetching: true
      }
    }
    case "FETCH_POSTS_REJECTED": {
      return {
        ...state,
        fetching: false,
        error: action.payload
      }
    }
    case "FETCH_POSTS_FULFILLED": {
      return {
        ...state,
        fetching: false,
        fetched: true,
        posts: action.payload
      }
    }
  }

  return state
}

And this is how I'm fetching category information:

export const fetchCategory = (id) => {
  return {
    type: "FETCH_CATEGORY",
    payload: axios.get(`${REST_URL}/wp/v2/categories/${id}`)
  }
}

Is there a way to combine my fetchPosts() action with the fetchCategory() action, so it populates the post.categories, returned from fetchPosts() with the more detailed fetchCategory() information?


Solution

  • If you're referring for ajax calls chaining you can use this example to understand how thunk can work for you:

    function loadSomeThings() {
        return dispatch => {
            fetchFirstThingAsync.then(data => { // first API call
                dispatch({ type: 'FIRST_THING_SUCESS', data }); // you can dispatch this action if you want to let reducers take care of the first API call
                return fetchSecondThingAsync(data), // another API call with the data received from the first call that returns a promise
            })
            .then(data => {
                 dispatch({ type: 'SECOND_THING_SUCESS', data }); // the reducers will handle this one as its the object they are waiting for
            });
        };
    }
    

    Basically when we call loadSomeThings we dispatch an new action as a function (fetchFirstThingAsync) as our first ajax call, redux-thunk will catch that before any reducer does as function are not the plain object that reducers can handle, thunk will invoke this function with dispatcher as an argument (along getState and some more args), we wait it out with .then and then we can dispatch a plain object that reducers can handle + returning another promise (fetchSecondThingAsync) that's your second ajax call, we wait it out with .then and again dispatching a plain object that reducers can handle.