0

I'm new to React, please keep this in mind.

I'm trying to render a list of recipes fetched from food2fork API but I can't get the view to update, even if the data is fetched correctly.

Here's recipe_list.js:

import React, { Component } from "react";
import { connect } from "react-redux";

    class RecipesList extends Component {
    // renderRecipe(recipe) {
    //     console.log(recipe);
    //     return (
    //         <div>{recipe}</div>
    //     );
    // }

    render() {
        console.log("Render function ", this.props.recipes)
            return (
            <div>
                <p>Recipes</p>
                <div>{this.props.recipes}</div>
            </div>
            );
    }
}

function mapStateToProps(state){
    return { recipes: state.recipes };
}

export default connect(mapStateToProps)(RecipesList);

Here's reducer_recipes.js:

import FETCH_RECIPES from "../actions/index";

export default function(state = [], action){
    switch (action.type) {
        case FETCH_RECIPES:
            return action.payload;
    }
    return state;
}

Here's /reducers/index.js:

import { combineReducers } from 'redux';
import RecipesReducer from "./reducer_recipes";

console.log(RecipesReducer);
const rootReducer = combineReducers({
  recipes: RecipesReducer
});

export default rootReducer;

Here's /actions/index.js:

import axios from "axios";

const API_KEY = "****************************";
export const URL = `https://food2fork.com/api/search?key=${API_KEY}`;


export const FETCH_RECIPES = "FETCH_RECIPES";

export function fetchRecipes(term){
    const url = `${URL}&q=${term}`;
    const request = axios.get(url);

    return {
        type: FETCH_RECIPES,
        payload: request
    };
}

I don't get any specific error. The view just doesn't update. I tried to spread some console.log around the files to try to understand where the problem is. It seems like the Reducer is not successfully delivering the payload to the component.

NOTE: I'm using react-promise so the promise returned from axios is automatically resolved.

Any ideas?

===================================================================

EDIT:

Thank you for the useful links but there is clearly something that I'm still missing here. I have modified the action index:

function getStuffSuccess(response) {
  return {
    type: FETCH_RECIPES,
    payload: response
  };
}

function getStuffError(err) {
  return {
    type: ERROR_FETCH_RECIPES,
    payload: err
  };
}

export function fetchRecipes(term) {
    const url = `${URL}&q=${term}`;

  return function(dispatch) {
    axios.get(url)
      .then((response) => {
        dispatch(getStuffSuccess(response));
      })
      .catch((err) => {
        dispatch(getStuffError(err));
      });
  };
}

I have also included redux-thunk to the store:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from "redux-promise";
import Thunk from 'redux-thunk';

import App from './components/app';
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware(Thunk, ReduxPromise)    (createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <App />
  </Provider>
  , document.querySelector('.container'));

The behaviour hasn't changed from before. The view is still not updating.

NOTE: If I console.log the payload from the Reducer the data is in there. But when I try to do the same in the View nothing happens.

Scaccoman
  • 455
  • 7
  • 16

2 Answers2

0

Your action is not synchronus here, you need to use Async Action to deliver the response to reducer, meaning, you have to dispatch the response instead of returning it. Check the given link for more details.

SALEH
  • 1,552
  • 1
  • 13
  • 22
  • To add to the above answer, you have to call the actions once the component is mounted. – Javed Dec 02 '17 at 19:07
0

I would try refactoring your /actions/index.js like so:

import axios from 'axios';

export const FETCH_RECIPES = 'fetch_recipes';
export const CREATE_RECIPE = 'create_recipe';

const ROOT_URL = '<url-of-api-endpoint>';
const API_KEY = '<api-key>';

export function fetchRecipes() {
  const request = axios.get(`${ROOT_URL}/posts${API_KEY}`);

  return {
    type: FETCH_RECIPES,
    payload: request
  };
}

export function createRecipe(values, callback){
  const request = axios.post(`${ROOT_URL}/posts${API_KEY}`, values)
  .then(() => callback());

  return {
    type: CREATE_RECIPE,
    payload: request
  }
}
Daniel
  • 14,004
  • 16
  • 96
  • 156