Somename Somename - 29 days ago 10
React JSX Question

Filter data received from an API call

How do I separate the data received from an API call and store it in a reducer?

My API call:

ACTION:

export function fetchCatsFromAPI() {
return(dispatch) => {
dispatch(getCats())
fetch(myapi)
.then(res => res.json())
.then(json => dispatch(getCatsSuccess(json))) // <= Dispatching the entire data.
.then(json => dispatch(getCatsTotalSuccess(json.total))) // <= This did not work.
.catch(err => dispatch(getCategoriesFailure(err)))
}
}


getCategories() : Dispatches FETCHING_CATEGORIES
getCategoriesSuccess() : Dispatches FETCHING_CATEGORIES_SUCCESS
getCategoriesFailure() : Dispatches FETCHING_CATEGORIES_FAILURE


The API call returns:

{"total":6,"categories":[{"id_cat":1,"name":"CAT01"},{"id_cat":2,"name":"CAT02"}]}


REDUCER:

const initialState = {
categories: [],
totalResults: '',
isAdding: false,
error: {}
}

export default function categories(state=initialState, action) {
switch(action.type) {
case "FETCHING_CATEGORIES":
return {
...state,
isAdding: true
}
case "FETCHING_CATEGORIES_SUCCESS":
return {
...state,
isAdding: false,
categories: action.data,
totalResults: action.data.total // <= This did not work.
}
case "FETCHING_CATEGORIES_FAILURE":
return {
...state,
isAdding: false,
error: action.err
}
default:
return state
}
}


Having another case for
getCatsTotalSuccess
also doesn't work for
json.total


I want to have a separate
var
for
categories
and
total
. How do I do this?

UPDATE 1: ACTIONS:

function getCats(){
return {
type:FETCHING_CATEGORIES
}
}

function getCatsSuccess(data){
return {
type:FETCHING_CATEGORIES_SUCCESS,
data
}
}

function getCatsTotalSuccess(data){
return {
type:FETCHING_CATEGORIES_TOTAL_SUCCESS,
data
}
}

function getCatsFailure(err){
return {
type:FETCHING_CATEGORIES_FAILURE,
err
}
}

Answer Source

In your dispath, inside your action, to code in the most followed convention in React, you need to send an object of two properties: type and payload. The payload will contain the data which your API returned and the type will be a reference to which reducer to update

You did not show what your action creators code contained, so instead, I am writing what should be a working version of your code. Including the action creators.

Here is how you action code should look:

import { 
    FETCHING_CATEGORIES_SUCCESS,
    FETCHING_CATEGORIES,
    FETCHING_CATEGORIES_FAILURE 
    } from 'constant-path'

export function fetchCatsFromAPI() {
  return(dispatch) => {
    dispatch({ type: FETCHING_CATEGORIES}) // We tell our store that we are iniaiting an API call. This is ideal to since network calls may take several MS to load. A spinner can be rendered while we are at this stage
     fetch(myapi)
    .then(res => res.json())
    .then(json => dispatch({ type: FETCHING_CATEGORIES_SUCCESS, payload: json))     // <= I believe here was your mistake 
    .catch(err => dispatch({ type: FETCHING_CATEGORIES_FAILURE, payload: err}))
  }
}

How your reducer should look:

import { 
FETCHING_CATEGORIES_SUCCESS,
FETCHING_CATEGORIES,
FETCHING_CATEGORIES_FAILURE 
} from 'constant-path' 

const initialState = {
  categories: [],
  totalResults: '',
  isAdding: false,
  error: {}
}

export default function categories(state=initialState, action) {
  switch(action.type) {
    case FETCHING_CATEGORIES:
      return {
        ...state,
        isAdding: true
      }
    case FETCHING_CATEGORIES_SUCCESS:
      return {
        ...state,
        ...payload
      }
    case FETCHING_CATEGORIES_FAILURE:
      return {
        ...state,
        isAdding: false,
        error: action.err
      }
    default: 
      return state
  }
}

Constant file would look like:

export const FETCHING_CATEGORIES_SUCCESS = 'FETCHING_CATEGORIES_SUCCESS';
export const FETCHING_CATEGORIES = 'FETCHING_CATEGORIES';
export const FETCHING_CATEGORIES_FAILURE = 'FETCHING_CATEGORIES_FAILURE';

With the above, you'd be secured from an annoying and common problem which developers encounter when they don't use constants when dispatching from actions towards the reducers.