MarkT
MarkT

Reputation: 127

Correct search statement when applying filters

I have created a search function for my React-native app, however, I am not quite sure how to create the correct search statement. What I have now is as follows. You can open a filter screen where you can type a few search criteria (for vehicles) so make, model, color, license plate.

After saving the filters you are re-directed to a result page. On this page, I populate a const with Redux data (the vehicle database) and then filter this data before showing it in flatlist.

const vehicles = useSelector(state => state.uploadedVehicles.vehicles)
const filters = props.navigation.getParam('savedFilters')

const filteredVehicles = vehicles.filter(vehicle => 
        vehicle.make === filters.makeFilter ||
        vehicle.model === filters.modelFilter ||
        vehicle.color === filters.licenseplateFilter ||
        vehicle
.licenseplate === filters.licenseplateFilter
        )



...return Flatlist with filteredVehicles here...

If I set a filter for a particular Make, only vehicles from this make are found. If I set a filter for a model, only vehicles from this model are found. However, if I set a filter for two statements it now shows vehicles with one matching search criteria. If I would search for a blue Dodge I would find vehicles matching the make Dodge, but also every blue vehicle that is uploaded.

How can I expand my search function so It will show vehicles matching 1 filter, but if 2 or more filters are added it will combine these filters to a more specific search function?

Upvotes: 0

Views: 56

Answers (2)

MarkT
MarkT

Reputation: 127

Maybe this isn't the most beautiful way of getting the filter to work. But I didn't quite get my filter working with MIPB his response bit it did push me in the right direction.

I am passing the filters in appliedFilters. Then I constantly checking every filter with the part of the vehicle that is filtered for.

Starting with the make of the vehicle. If the make filter is nog set (so "") I just return the vehicles array which contains every vehicle, else I return every vehicle that is matched with the appliedFilters.makeFilters.

This new makeFilterArray is checked with the modelFilter. If this is not set just set it to the makeFilter array to continue checking other filters, if it is set check the makeFilterArray for the matching model.

Maybe not the best/most elegant solution, but with my limited knowledge I got it working! :-)

case FILTER_VEHICLES: 
const appliedFilters = action.setFilters; 
console.log(appliedFilters)
console.log(appliedFilters.makeFilter)
console.log(appliedFilters.modelFilter)
console.log(appliedFilters.licenseplateFilter)
console.log(appliedFilters.colorFilter)
const makeFilterArray = appliedFilters.makeFilter === "" ? vehicles : state.vehicles.filter(vehicle => vehicle.make === appliedFilters.makeFilter)
const modelFilterArray = appliedFilters.modelFilter === "" ? makeFilterArray : makeFilterArray.filter(vehicle => vehicle.model === appliedFilters.modelFilter)
const licenseplateFilterArray = appliedFilters.licenseplateFilter === "" ? modelFilterArray : modelFilterArray.filter(vehicle => vehicle.licenplate === appliedFilters.licenseplate)
const filteredArray = appliedFilters.colorFilter === "" ? licenseplateFilterArray : licenseplateFilterArray.filter(vehicle => vehicle.color === appliedFilters.color)

// and now you will return an updated array of data only for the applied filters
return {
  ...state,
  filteredVehicles: filteredArray
};

Upvotes: 1

MIPB
MIPB

Reputation: 2471

I like to take another approach to this, also using Redux. Here I show you an example code:

 case SAVE_FILTERS: {
      const appliedFilters = state.filters; // Here you have your filters that have to be 
      initialized in your state. They also have to be turned to true or false but you can 
      do it in another function (See next one)

      // Here we check every condition
      const updatedData = state.data.filter(data => { 
        if (appliedFilters.filter1 && !data.filter1) {
          return false;
        }
        if (appliedFilters.filter2 && !data.filter2) {
          return false;
        }
        if (appliedFilters.filter3 && !data.filter3) {
          return false;
        } else {
          return true;
        }
      });
// and now you will return an updated array of data only for the applied filters
      return {
        ...state,
        displayData: updatedLocations,
      };

The trick is to check every single condition inside of the action. In this particular case, we are checking by filters that are true or not, but you can expand to other conditionals.

The flow for the code above is:

If we have a filter applied AND the data HAS that filter, then we pass the conditional. WE do this for all conditionals. If we pass all of them, return true which means it will be added to the display data and the user will see it.

I hope it helps.

Upvotes: 1

Related Questions