Easy-peasy: Fetch from Cloud Firestore

Created on 3 Dec 2018  路  11Comments  路  Source: ctrlplusb/easy-peasy

I am trying to fetch data from my Cloud Firebase, but I can't figure out how to do it. I tried following the guide, but nothing works. I am only getting in an endless loop. What am I doing wrong?

My store

article: {
    items: [],

    fetch: effect(async (dispatch, payload, getState) => {
      const saved = firebase
        .firestore()
        .collection("article")
        .get()
        .then(function(querySnapshot) {
          querySnapshot.forEach(function(doc) {
            return doc.data();
          });
        });

      dispatch.article.fetched(saved);
    }),

    fetched: (state, payload) => {
      state.items.push(payload);
    }
  },
  // effects
  initialise: effect(async dispatch => {
    await dispatch.article.fetch();
  })

My simple article component:

import { useStore } from "easy-peasy";

const Articles = () => {
  const articles = useStore(state => state.article.items);
  return (
    <div>
      <div>Articles:</div>
      {articles.map(item => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
};

Most helpful comment

It is more advised to just use the [] argument option, like:

useEffect(() => {
   // actions here
}, [])

All 11 comments

Your integration with firebase isn't really correct, the forEach method that you area calling doesn't return to the "then" method, you have to set an accumulator and then pass it to the dispatcher. Also, you're probably dispatching before the articles are fetched.

You could try something like this:

fetch: effect(async (dispatch, payload, getState) => {
const articleCollection = firebase.firestore().collection("article");

const articles = await articleCollection.get();

const saved = [];

articles.forEach(function (doc) {
    saved.push(doc.data());
});
dispatch.article.fetched(saved);

})

You could try something like this:

fetch: effect(async (dispatch, payload, getState) => {
const articleCollection = firebase.firestore().collection("article");

const articles = await articleCollection.get();

const saved = [];

articles.forEach(function (doc) {
    saved.push(doc.data());
});
dispatch.article.fetched(saved);

})

Thanks, that was smart! I tried that, but I still get an endless loop and no data shown when trying to render. Also tried to console.log the state... endless loop here too.

const articles = useStore(state => state.article.items);
useEffect(() => {
    console.log(articles)
});

Where are you calling the "initialise" method?

In the parent component of the Article component.

const App = () => {
  const initialise = useAction(actions => actions.initialise);
  const articles = useStore(state => state.article.items);

  useEffect(() => {
    /*initialise();*/  //removed because of endless looop
    console.log(articles); //returns nothing
  });
  return (
    <Article />
  )
}

That's it, you shoudn't call the initialise method inside the useEffect hook

The Easy-Peasy example did that. Where should it be called then? Where ever I call it it goes to infinite loop..

The useEffect triggers whenever your app mount, and when your state update, so when the articles are fetched, it will call the useEffect again... You can call the initialise method outside the useEffect, or simple add the second argument [] to useEffect, so it will run only on the initial mount.

Edit: Dont't call the method outside the useEffect, follow the example of my next comment.
Edit II: Also, the Easy-Peasy example is not directly using the state on the component it is calling "initialise", so it can call the initialise method without rerendering the component.

It is more advised to just use the [] argument option, like:

useEffect(() => {
   // actions here
}, [])

Ahhhh!!! Solved it. Where can I find info about second argument []? Nothing in the React docs.

Also had to change the fetched action to this:

   fetched: (state, payload) => {
      return {
        ...state,
        items: payload
      };
    }

You can find more about the [] argument in the docs, look for the footer note:
https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

Was this page helpful?
0 / 5 - 0 ratings