henrydoe
henrydoe

Reputation: 397

can't load post from api

I'm trying to retrieve post from the api using redux but it doesn't load any post from the api. It does load the dummy snippets I've created in the initialState but not the posts that are saved in the database using the api. What wrong am I doing in trying to retrieve the posts from my api?

My action file where I made the api call

import { SAVE_POST, UPDATE_POST, RETRIEVE_POST, HOME_LOADED } from "./types";
import axios from "axios";
export const savePost = ({
  snippetId,
  snippetDescription,
  snippetTitle
}) => async dispatch => {
  const config = {
    headers: {
      "Content-Type": "application/json"
    }
  };
  let snippetData = { snippetId, snippetDescription, snippetTitle };
  try {
    if (snippetId == null) {
      const res = await axios.post(
        "/api/save",
        JSON.stringify(snippetData),
        config
      );
      snippetData.snippetId = res.data;
      dispatch({
        type: SAVE_POST,
        payload: snippetData
      });
    } else {
      await axios.post("/api/update", JSON.stringify(snippetData), config);
      dispatch({
        type: UPDATE_POST,
        payload: snippetData
      });
    }
  } catch (err) {
    console.log(err);
  }
};

// Retrieve post

export const retrievePost = snippetId => async dispatch => {
  try {
    const res = await axios.post(`/api/snippetdata/${snippetId}`);
    dispatch({
      type: RETRIEVE_POST,
      payload: res.data
    });
  } catch (err) {
    console.error(err);
  }
};

//Retrieve all the post
export const onLoad = () => async dispatch => {
  try {
    const res = await axios.post(`/api/mysnippets/`);
    dispatch({
      type: HOME_LOADED,
      payload: res.data
    });
  } catch (err) {
    console.error(err);
  }
};

the home page where I call the action to retrieve the post

import React from "react";
// import axios from "axios";
import { Link } from "react-router-dom";
import { onLoad, setEdit } from "./actions/posts";
import { connect } from "react-redux";

// import { Form } from "../../components/Article";

class Home extends React.Component {
  // constructor(props) {
  //   super(props);
  // }

  componentDidMount() {
    //Load all the snippets
    onLoad(); // this isn't loading the post from server
  }

  render() {
    const { snippets } = this.props;
    console.log(this.props);
    let view;
    if (snippets) {
      view = snippets.map(snippet => {
        return (
          <div className="card my-3" key={snippet.snippetId}>
            <div className="card-header">{snippet.title}</div>
            <div className="card-body">{snippet.snippetDescription}</div>
            <div className="card-footer">
              <div className="row">
                <button
                  // onClick={() => this.handleEdit(snippet)}
                  className="btn btn-primary mx-3"
                >
                  <Link to={`/editor/:${snippet.snippetId}`}>Edit</Link>
                </button>
              </div>
            </div>
          </div>
        );
      });
    }

    return (
      <div className="container">
        <div className="row pt-5">
          <div className="col-12 col-lg-6 offset-lg-3">
            <h1 className="text-center">Snippets</h1>
          </div>
        </div>
        <div className="row pt-5">
          <div className="col-12 col-lg-6 offset-lg-3">{view}</div>
        </div>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  snippets: state.snippets,
  snippetData: state.snippetData
});

export default connect(
  mapStateToProps,
  { onLoad, setEdit }
)(Home);

reducer.js

import {
  SAVE_POST,
  UPDATE_POST,
  RETRIEVE_POST,
  HOME_LOADED
} from "../actions/types";

import { initialState } from "../store";

export default function(state = initialState, action) {
  const { type, payload } = action;
  switch (type) {
    case SAVE_POST:
      return {
        ...state,
        snippetData: payload
      };
    case UPDATE_POST:
      return {
        ...state,
        snippetData: payload
      };
    case RETRIEVE_POST:
      return {
        ...state,
        snippetData: payload
      };
    case HOME_LOADED:
      return {
        ...state,
        snippets: payload
      };
    case "SET_EDIT":
      return {
        ...state,
        snippetToEdit: action.snippet
      };
    default:
      return state;
  }
}

codesandbox of the entire webapp

Upvotes: 1

Views: 60

Answers (1)

Ram Sankhavaram
Ram Sankhavaram

Reputation: 1228

import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import posts from "./reducers/posts";

export const initialState = {
  snippets: [
    {
      snippetId: "1",
      snippetTitle: "test",
      snippetDescription: "test test"
    },
    {
      snippetId: "2",
      snippetTitle: "post2",
      snippetDescription: "post 2 post2"
    }
  ],
  snippetData: {
    snippetId: null,
    snippetTitle: null,
    snippetDescription: null
  }
};
const store = createStore(posts, applyMiddleware(thunk));
export default store;

Above is the store.js file which has to be updated with middleware.

Since you are making network calls, you got to use a middleware like redux thunk to handle async operations as basic redux store only allows you to do the synchronous updates but not async. These help us to return a function rather than action. Hope this helps!

//Dispatch function:
    export const onLoad = () => {
      return async dispatch => {
        console.log("dispatched");
        try {
          const res = axios.post(`/api/mysnippets/`);
          dispatch({
            type: HOME_LOADED,
            payload: res.data
          });
    } catch (err) {
      console.error(err);
    }
  };
};

Upvotes: 2

Related Questions