Open
Description
Hi,
Firstly, I have found the patterns in the guide very helpful for configuring actions, epics, reducers etc. However, I do not understand how to dispatch a fetch API request action and subsequently bind to a fetch successful action. I have managed to create an epic for a fetch API request that then triggers a success or error action depending upon the success/failure of the API request.
I do not understand how to hook this up to a functional component, as highlighted in the comments of the CourseList functional component code listing below:
CourseList Functional Component
import React, { useEffect } from 'react';
import Grid from '@material-ui/core/Grid';
import { GridSpacing } from '@material-ui/core/Grid';
import Course from '../../components/Course/Course';
import { Course as CourseModel } from '../../redux/features/course/model';
type Props = {
courses: CourseModel[];
onFetchCourseRequest: ??? // I want to bind this to the fetch courses action but do not understand how?? what type should this be??
};
export const CourseList: React.FC<Props> = props => {
const { courses, onFetchCourseRequest } = props;
// functional equivalent of componentDidMount
// this only gets triggered once, since
// dependency list is empty
// I want this to to trigger the dispatch of a FETCH_COURSE_LIST action and bind to resulting FETCH_COURSE_LIST
// I do not understand how to do this from examples....
useEffect(() => {
onFetchCourseRequest();
}, []);
return (
<div style={{ marginTop: 20, padding: 30 }}>
{
<Grid container spacing={2 as GridSpacing} justify="center">
{courses.map(element => (
<Grid item key={element.courseID}>
<Course course={element} />
</Grid>
))}
</Grid>
}
</div>
);
};
CourseListConnected
import { RootState } from 'ReduxTypes';
import { connect } from 'react-redux';
import { CourseList } from './CourseList';
import { courseActions, courseSelectors } from '../../redux/features/course';
const mapDispatchToProps = {
onFetchCoursesRequest: courseActions.fetchCoursesRequest,
};
const mapStateToProps = (state: RootState) => ({
courses: courseSelectors.getReduxCourses(state.courses.fetchCoursesSuccess),
});
const CourseListConnected = connect(
mapStateToProps,
mapDispatchToProps,
)(CourseList);
export default CourseListConnected;
Epic for Fetching a Course from API
import { RootAction, RootState, Services } from 'ReduxTypes';
import { Epic } from 'redux-observable';
import { isOfType } from 'typesafe-actions';
import { of } from 'rxjs';
import {
catchError,
filter,
ignoreElements,
map,
switchMap,
} from 'rxjs/operators';
import { fetchCoursesFail, fetchCoursesSuccess } from './actions';
import constants from './constants';
export const fetchCoursesRequestAction: Epic<
RootAction,
RootAction,
RootState,
Services
> = (action$, state$, { courseServices }) =>
action$.pipe(
filter(isOfType(constants.FETCH_COURSES_REQUEST)),
switchMap(action =>
courseServices.default.getCourses().pipe(
map(courses => fetchCoursesSuccess(courses)),
catchError(error => of(fetchCoursesFail(error))),
),
),
ignoreElements(), // ignore everything except complete and error, template does this
);
Metadata
Metadata
Assignees
Labels
No labels