2

I'm a beginner of react native. If you give me any advice, it would be helpful and I would appreciate you.

I'm trying to fetch data from firestore using react-native, immutable.js, react-redux, redux-actions also this codes follow ducks structure. The problem is that I can't get any data from firestore because data from firestore comes after reducer executed.

Even, I'm not sure if I could put firestore fetching method as second parameter of createAction.

Here's my code.


shared/index.js

import firebase from 'firebase/app';
import 'firebase/firestore'
import 'firebase/storage'

const config = {
  apiKey: "...",
  authDomain: "...",
  databaseURL: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "..."
};

firebase.initializeApp(config);
const db = firebase.firestore();
const storage = firebase.storage();

export const getCategoryNames = () => {
  return db.collection('categories').get();
}

store/modules/categoryImgList

import {createAction, handleActions} from 'redux-actions';
import { Map, List } from 'immutable';

// firestore
import * as db from '../../shared';

// Action types
const GET_NAME = 'categoryImgList/GET_NAME';

// action creator
export const getName = createAction(GET_NAME, () => {
  db.getCategoryNames().then(data => {
    const arr = [];

    data.forEach(doc => {
        console.log(doc.data().name);
        arr.push(doc.data().name);
    });

    console.log('arr');
    console.log(arr);
  })
}); // none

const initialState = Map({
    name: List()
});

// Reducer
export default handleActions({
    [GET_NAME]: (state, { payload: name }) => {
      console.log(state);
      console.log({name});
      const item = Map({ name });
      return state.update('name', name => name.push(item));
    }
}, initialState);

Thank you so much!

Mingyu Jeon
  • 1,755
  • 5
  • 23
  • 40
  • The way I typically do it is to dispatch the action after I have retrieved data from firestore. In this case, though, it doesn't look like you do anything with the data after you add it to the array besides log it. You handle the resolution by loading it into the array, but then I believe you would have to return the array or something along those lines. How does is it supposed to get into the payload? – Noah Allen Jun 16 '18 at 01:34
  • Thanks for the reply! It supposed to get data as an array, so it would be `[...name]` – Mingyu Jeon Jun 16 '18 at 07:26

1 Answers1

1

I solved this issue by my self. I realized I needed redux-thunk to get async data. I installed redux-thunk and changed some code as below.

import {handleActions} from 'redux-actions';

// firestore
import * as db from '../../shared';

// Action types
const GET_CATEGORY_NAME_PENDING = 'categoryImgList/GET_CATEGORY_NAME_PENDING';
const GET_CATEGORY_NAME_SUCCESS = 'categoryImgList/GET_CATEGORY_NAME_SUCCESS';
const GET_CATEGORY_NAME_FAILURE = 'categoryImgList/GET_CATEGORY_NAME_FAILURE';

// action creator
export const getName = () => async (dispatch) => {
  dispatch({type: GET_CATEGORY_NAME_PENDING});
  try {
    const response = await db.getCategoryNames();

    const arr = [];
    response.docs.forEach(res => {
        arr.push(res.id);
    });
    console.log(arr);

    dispatch({type: GET_CATEGORY_NAME_SUCCESS, payload: arr});
    return arr;
  } catch (e) {
      console.log(e);
      dispatch({type: GET_CATEGORY_NAME_FAILURE, payload: e});
  }
}

const initialState = {
  fetching: false,
  error: false,
  name: []
};

// Reducer
export default handleActions({
  [GET_CATEGORY_NAME_PENDING]: (state) => ({ ...state, fetching: true, error: false }),
  [GET_CATEGORY_NAME_SUCCESS]: (state, action) => ({ ...state, fetching: false, name: action.payload }),
  [GET_CATEGORY_NAME_FAILURE]: (state) => ({ ...state, fetching: false, error: true })
}, initialState);
Mingyu Jeon
  • 1,755
  • 5
  • 23
  • 40