kenpeter
kenpeter

Reputation: 8294

How to assign return of async value to initial state of reducer?

Full code: https://github.com/kenpeter/test_infinite_scroll_1

I have a reducer. It has a prop called list. createList([], 0) calls remote api and gets data, then assign to list.

./reducers/loadMore.js

import { MORE_LIST } from "../actions/types";
import { createList } from "../utils/func"; 

const initState = {
  list: createList([], 0) // <--------------------
};

// able to fire
export default function list(state = initState, action = {}) {
  switch(action.type) {

    case MORE_LIST:
      return {
        list: action.list,
      }

    default:
      return state;
  }
}

./utils/func.js

import _ from 'lodash';
import axios from "axios";

// clone the array
export function createList(arr=[],start=0) {
  let apiUrl = "http://www.mangaeden.com/api/list/0?p=0";

  return axios.get(apiUrl).then((obj) => {
    let arr = obj.data.manga; // array of obj

    //console.log("--- start ---");
    //console.log(arr);  

    return arr;        
  });
}  

The issue I have with function createList(arr=[],start=0) is arr has data from remote api, but it is not able to return back to list in ./reducers/loadMore.js

Upvotes: 2

Views: 1006

Answers (2)

Moinul Hossain
Moinul Hossain

Reputation: 2206

Your createList returns a Promise. So in your client/actions/loadMore.js you need to do:

return createList(list, list.length+1).then((tmpList) => {
    dispatch({
      type: MORE_LIST,
      list: tmpList
    });
});

Also, as patric mentioned, the following code in client/reducers/loadMore.js is async,

const initState = {
  list: createList([], 0)
};

the initState.list here is a Promise. Instead initialize it with empty list and dispatch the loadMore() action in the ComponentDidMount method of your component/container

Upvotes: 0

patrick
patrick

Reputation: 10273

I feel that making ajax requests in your initial state for your reducer is an anti-pattern.

Instead, I would just have the initial state as an empty array and then either as your app starts or in an appropriate component's lifecycle (componentWillMount for example) I would dispatch an action to fetch the data.

You can use indicators like loading bars/spinners etc. to indicate to the user that data is coming back. Additionally, you can perform a check on the length of your array or just do a .map on the empty array anyway and this won't get errors.

Upvotes: 6

Related Questions