React Redux Filter on data from json file

I’m trying to use redux to load a json file from a client-side server, then also use redux to filter on that data. The data entries contain coordinates on a map as well as priority and status categories, which is what I need to filter on. I was able to successfully load the file using redux action/reducer/selector and store the data in state, but I’m having difficulty filtering on the data. I’ve been trying to understand how to use these but it’s not making sense to me.

If anyone could take a look at my code and tell me what I’m doing wrong that would be greatly appreciated. As it is now, using the filter selector doesn’t do anything. It seems my actions are not being dispatched.

Here is the functional component Filter that I’m having trouble with:

Filter.jsx

import React from 'react';
import { connect } from "react-redux";
import {setPriority, setStatusFilter} from '../redux/actions/jobs';


export function Filter(props) {
    //const { error, loading, jobs } = this.props;
    const handlePriority = (event) => {
        //console.log(jobs);
        setPriority(event.target.value);
    };
    const handleStatus = (event) => {
        setStatusFilter(event.target.value);
    };

    if (props.type === "priority") {
        return (
            <select onChange={handlePriority}>
                <option defaultValue="all">All</option>
                <option value="high">High</option>
                <option value="medium">Medium</option>
                <option value="low">Low</option>
            </select>
        );
    }
    if (props.type === "status") {
        return (
            <select onChange={handleStatus}>
                <option defaultValue="all">All</option>
                <option value="assigned">Assigned</option>
                <option value="unassigned">Unassigned</option>
                <option value="in_progress">In Progress</option>
                <option value="completed">Completed</option>
            </select>
        );
    }

}
const mapDispatchToProps = () => {
    return {
        setPriority: setPriority
    }
};

// const mapStateToProps = state => ({
//     jobs: state.jobs,
//     loading: state.jobs.loading,
//     error: state.jobs.error
//   });

export default connect(mapDispatchToProps) (Filter);
// export default Filter;

(I’ve included the redux actions, reducers and selectors below.)

When I try to call setPriority in this way, it hits the setPriority function in my redux actions successfully and fires off the console.log, but then it does not seem to dispatch setPriorityFilter as the console.log within that function is not displayed. Also, in my redux chrome extension, SET_PRIORITY_FILTER isn’t hit.

Here is the Map class-based component where I actually load the jobs and display them on the map, calling loadJobs from the redux actions:

Map.jsx

import React, { Component } from 'react';
import { connect } from 'react-redux';
import GoogleMapReact from 'google-map-react';
import MapMarker from './MapMarker';
import { loadJobs } from '../redux/actions/jobs';

class JobMap extends Component {
  componentDidMount() {
    this.props.dispatch(loadJobs());
  }

  static defaultProps = {
    center: {
      lat: 42.396308,
      lng: -71.272355
    },
    zoom: 10
  };

  render() {
    const { error, loading, jobs } = this.props;
    if (error) {
      return <div>Error! {error.message}</div>;
    }

    if (loading) {
      return <div>Loading...</div>;
    }
    return (
      <div style={{ float:'left',  height: '100vh', width: '70%' }}>
        <GoogleMapReact
          bootstrapURLKeys={{ key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }}
          defaultCenter={this.props.center}
          defaultZoom={this.props.zoom}
          options={{ disableDoubleClickZoom: true, fullscreenControl: false }}
        >
          {jobs.allJobs.jobs 
          ? jobs.allJobs.jobs.map(job => 
            <MapMarker key={job.id} lat={job.lat} lng={job.long} priority={job.priority}/>) 
          : <MapMarker lat={42.396308} lng={-71.272355}/>
          }
        </GoogleMapReact>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  jobs: state.jobs,
  loading: state.jobs.loading,
  error: state.jobs.error
});
export default connect (mapStateToProps)(JobMap);

Here are the redux actions: /redux/actions/jobs.js

export const loadJobs = () => {
    return dispatch => {
        dispatch(loadJobsBegin());
        return fetch('/jobs')
            .then(handleErrors)
            .then(response => response.json())
            .then(jobs => {
                dispatch(loadJobsSuccess(jobs));
                // console.log(jobs)
                return jobs;
        })
        .catch(error => dispatch(loadJobsFailure(error)));
    };
};

// Handle HTTP errors
export const handleErrors = (response) => {
    if (!response.ok) {
      throw Error(response.statusText);
    }
    return response;
};

export const loadJobsBegin = () => ({
    type: 'LOAD_JOBS_BEGIN'
});

export const loadJobsSuccess = jobs => ({
    type: 'LOAD_JOBS_SUCCESS',
    payload: { jobs }
});

export const loadJobsFailure = error => ({
    type: 'LOAD_JOBS_FAILURE',
    payload: { error }
});


export const setPriority = (priority) => {
    console.log("you made it")
    return dispatch => {
        dispatch(setPriorityFilter());
        console.log("you made it 2");
        return priority
    }
}

export const setPriorityFilter = priority => ({
    type: 'SET_PRIORITY_FILTER',
    payload: {priority}
})
// export const setPriorityFilter = priority => dispatch => {
//     console.log("hello");
//     dispatch({ type: 'SET_PRIORITY_FILTER', jobs: priority });
// };

export const setStatusFilter = status => dispatch => {
    dispatch({ type: 'SET_STATUS_FILTER', jobs: status });
};

Here are the redux reducers: /redux/reducers/jobs.js

const initialState = {
    allJobs: [],
    priorityFilter: 'all',
    statusFilter: 'all',
    dateFilter: ''
};

export default function jobs(state = initialState, action) {
    switch (action.type) {
      case 'LOAD_JOBS_BEGIN': {
        return {
          ...state,
          loading: true,
          error: null
        };
      }
      case 'LOAD_JOBS_SUCCESS': {
        return {
          ...state,
          loading: false,
          allJobs: action.payload
        };
      }
      case 'LOAD_JOBS_FAILURE': {
        return {
          ...state,
          loading: false,
          error: action.payload.error,
          allJobs: []
        };
      }
      case 'SET_PRIORITY_FILTER': {
        return {
          ...state,
          priorityFilter: action.priority,
          // allJobs: action.payload
        };
      }
      case 'SET_STATUS_FILTER': {
        return {
          ...state,
          statusFilter: action.status,
          // allJobs: action.payload
        };
      }
      default:
        return state;
    }
  }

And here are the redux selectors: /redux/selectors/jobs.js

export const selectJobsSuccess = state => state.jobs.allJobs;

export const selectPriorityFilter = state => state.jobs.priorityFilter;

export const selectStatusFilter = state => state.jobs.statusFilter;

79 thoughts on “React Redux Filter on data from json file”

Leave a Comment