-
-
Save simonelp/45f73739fa71fd6dfc0d to your computer and use it in GitHub Desktop.
React Filter HoC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { Component } from 'react'; | |
let Filter = Filterable => class extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
items: props.items | |
}; | |
} | |
componentDidUpdate(prevProps, prevState) { | |
if (prevProps.filter !== this.props.filter || prevProps.items !== this.props.items) { | |
this.updateFilter(); | |
} | |
} | |
componentDidMount() { | |
this.updateFilter(); | |
} | |
updateFilter() { | |
let items = []; | |
let filter = {}; | |
// Transform the filter values | |
Object.keys(this.props.filter).forEach( key => { | |
let transform = this.props.filterTransform[key]; | |
let filterValue = transform ? transform(this.props.filter[key]) : this.props.filter[key]; | |
if (filterValue === null || typeof filterValue === "undefined") { | |
return; | |
} | |
filter[key] = filterValue; | |
}); | |
// Apply the transformed filter to each item | |
this.props.items.forEach( item => { | |
let itemSatisifesFilters = true; | |
for (let key in filter) { | |
let value = item[key]; | |
let filterValue = filter[key]; | |
// Numeric Value | |
if (filterValue.constructor === Number) { | |
if (filterValue !== value) { | |
itemSatisifesFilters = false; | |
} | |
} | |
// String Value | |
if (filterValue.constructor === String) { | |
if (value.trim().indexOf(filterValue) === -1) { | |
itemSatisifesFilters = false; | |
} | |
} | |
// Boolean Value | |
if (filterValue.constructor === Boolean) { | |
if (filterValue !== !!value) { | |
itemSatisifesFilters = false; | |
} | |
} | |
// Range Value | |
if (Array.isArray(filterValue)) { | |
if (value < filterValue[0] || value > filterValue[1]) { | |
itemSatisifesFilters = false; | |
} | |
} | |
} | |
if (itemSatisifesFilters) { | |
items.push(item); | |
} | |
} ); | |
this.setState({items}); | |
} | |
render() { | |
return ( | |
<Filterable {...this.props} items={this.state.items}/> | |
); | |
} | |
} | |
Filter.propTypes = { | |
items: React.PropTypes.array.isRequired, | |
filter: React.PropTypes.object.isRequired, | |
filterTransform: React.PropTypes.object | |
} | |
Filter.defaultProps = { | |
filterTransform: {} | |
} | |
Filter.negate = value => !!!value; | |
Filter.notZero = value => parseInt(value) !== 0 ? value : null; | |
Filter.range = range => value => value ? [parseFloat(value) * (1 - parseFloat(range)), parseFloat(value) * (1 + parseFloat(range))] : null; | |
Filter.integer = value => parseInt(value) || null; | |
Filter.chain = (...filters) => value => { filters.forEach(f => { value = f(value) }); return value; } | |
Filter.ignore = value => null; | |
export default Filter; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment