- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1.1k
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