api calls and redux thunk
parent
bf2eef21f2
commit
04d8e062d4
|
@ -0,0 +1,17 @@
|
|||
export async function handleResponse(response) {
|
||||
if (response.ok) return response.json();
|
||||
if (response.status === 400) {
|
||||
// So, a server-side validation error occurred.
|
||||
// Server side validation returns a string error message, so parse as text instead of json.
|
||||
const error = await response.text();
|
||||
throw new Error(error);
|
||||
}
|
||||
throw new Error("Network response was not ok.");
|
||||
}
|
||||
|
||||
// In a real app, would likely call an error logging service.
|
||||
export function handleError(error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("API call failed. " + error);
|
||||
throw error;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { handleResponse, handleError } from "./apiUtils";
|
||||
const baseUrl = process.env.API_URL + "/authors/";
|
||||
|
||||
export function getAuthors() {
|
||||
return fetch(baseUrl).then(handleResponse).catch(handleError);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import { handleResponse, handleError } from "./apiUtils";
|
||||
const baseUrl = process.env.API_URL + "/courses/";
|
||||
|
||||
export function getCourses() {
|
||||
return fetch(baseUrl).then(handleResponse).catch(handleError);
|
||||
}
|
||||
|
||||
export function saveCourse(course) {
|
||||
return fetch(baseUrl + (course.id || ""), {
|
||||
method: course.id ? "PUT" : "POST", // POST for create, PUT to update when id already exists.
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify(course)
|
||||
})
|
||||
.then(handleResponse)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
export function deleteCourse(courseId) {
|
||||
return fetch(baseUrl + courseId, { method: "DELETE" })
|
||||
.then(handleResponse)
|
||||
.catch(handleError);
|
||||
}
|
|
@ -5,37 +5,14 @@ import PropTypes from "prop-types";
|
|||
import { bindActionCreators } from "redux";
|
||||
|
||||
class CoursesPage extends React.Component {
|
||||
state = {
|
||||
course: {
|
||||
title: ""
|
||||
}
|
||||
};
|
||||
|
||||
handleChange = (event) => {
|
||||
const course = { ...this.state.course, title: event.target.value };
|
||||
this.setState({ course });
|
||||
};
|
||||
|
||||
handleSubmit = (event) => {
|
||||
event.preventDefault();
|
||||
this.props.actions.createCourse(this.state.course);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<>
|
||||
<h2>Courses</h2>
|
||||
<h3>Add Course</h3>
|
||||
<input
|
||||
type="text"
|
||||
onChange={this.handleChange}
|
||||
value={this.state.course.title}
|
||||
/>
|
||||
<input type="submit" value="Save" />
|
||||
{this.props.courses.map((course) => (
|
||||
<div key={course.title}>{course.title}</div>
|
||||
))}
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export const CREATE_COURSE = "CREATE_COURSE";
|
||||
export const LOAD_COURSES_SUCCESS = "LOAD_COURSES_SUCCESS";
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
import * as types from "./actionTypes";
|
||||
import * as courseApi from "../../api/courseApi";
|
||||
|
||||
export function createCourse(course) {
|
||||
return { type: types.CREATE_COURSE, course };
|
||||
}
|
||||
|
||||
function loadCoursesSuccess(courses) {
|
||||
return { type: types.LOAD_COURSES_SUCCESS, courses };
|
||||
}
|
||||
|
||||
export function loadCourses() {
|
||||
return function (dispatch) {
|
||||
return courseApi
|
||||
.getCourses()
|
||||
.then((courses) => {
|
||||
dispatch(loadCoursesSuccess(courses));
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { createStore, applyMiddleware, compose } from "redux";
|
||||
import rootReducer from "./reducers";
|
||||
import reduxImmutableStateInvariant from "redux-immutable-state-invariant";
|
||||
import thunk from "redux-thunk";
|
||||
|
||||
export default function configureStore(initialState) {
|
||||
const composeEnhancers =
|
||||
|
@ -9,6 +10,6 @@ export default function configureStore(initialState) {
|
|||
return createStore(
|
||||
rootReducer,
|
||||
initialState,
|
||||
composeEnhancers(applyMiddleware(reduxImmutableStateInvariant()))
|
||||
composeEnhancers(applyMiddleware(thunk, reduxImmutableStateInvariant()))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ module.exports = {
|
|||
https: false
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
"process.env.API_URL": JSON.stringify("http://localhost:3001")
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: "src/index.html",
|
||||
favicon: "src/favicon.ico"
|
||||
|
|
Loading…
Reference in New Issue