0

I am currently developing an application that is a copy of Instagram. It works with React-Redux, calls an external API via axios to fetch photos that are actually blog posts. I need to also pass the amount of likes (so 0) for each one, that I am adding in my fetchPhotos action creator, which causes my application to crash. This works fine whenever the action creator is only returning type and payload.

When I console logged the action it actually turned out that the promise is now not being resolved and thus followed the error.

Action creator:

 export function fetchPhotos() {
  const response = axios.get("https://dog.ceo/api/breed/husky/images");
  return {
    type: FETCH_PHOTOS,
    payload: response,
    likes: 0
  };
}

Reducer:

export default function(state = [], action) {  
  switch(action.type) {
    case FETCH_PHOTOS:
    console.log(action);
      return [action.payload.data.message, action.likes];
    default:
      return state;
  }  
}

In App:

const history = createBrowserHistory();

const store = createStore(
  connectRouter(history)(reducers),
  compose(applyMiddleware(routerMiddleware(history), ReduxPromise))
);

Is there any way to make the action creator actually resolve this promise inside the action.payload?

llievredemars
  • 170
  • 2
  • 15
  • I believe this happens as the action is not [FSA-compliant](https://github.com/redux-utilities/flux-standard-action): "An action MUST NOT include properties other than type, payload, error, and meta." – fshauge Jul 23 '18 at 19:23
  • That would make a lot of sense! Do you have any type of recommendation on how to include this type of information besides adding a data folder with fixed votes number? – llievredemars Jul 23 '18 at 19:28

2 Answers2

2

For documentation:

As @fshauge mentioned, the payload has to be a promise and adding the property of likes breaks it. I found this in the issues, which has solved my issue. The likes property actually has to go into meta, so the end result that functions correctly is:

export function fetchPhotos() {
  const response = axios.get("https://dog.ceo/api/breed/husky/images");
  return {
    type: FETCH_PHOTOS,
    payload: response,
    meta: {
      likes: 0
    }
  };
}
llievredemars
  • 170
  • 2
  • 15
0

According to the documentation of redux-promise, it expects either a promise or a Flux Standard Action (FSA) where the payload is a promise. Since adding the 'likes' property breaks FSA-compliancy, it has to be inside the payload somehow.

I suggest returning a promise directly from the action creator with the 'likes' property embedded as follows:

export async function fetchPhotos() {
  const response = await axios.get("https://dog.ceo/api/breed/husky/images");
  return {
    type: FETCH_PHOTOS,
    payload: {
      data: response.data,
      likes: 0
    }
  };
}

redux-promise will automatically call dispatch when the promise resolves, and you can use the following code in your reducer:

export default function (state = [], action) {
  switch (action.type) {
    case FETCH_PHOTOS:
      console.log(action);
      return [action.payload.data.message, action.payload.likes];
    default:
      return state;
  }
}
fshauge
  • 117
  • 1
  • 3
  • 8