0.2.0 • Published 6 years ago

react-reduce v0.2.0

Weekly downloads
4
License
ISC
Repository
github
Last release
6 years ago

react-reduce

Sometimes there is a need in "react" to implement filters in our application. The most common task of a filter is to filter the received list. The react-reduce module provides a convenient filter set-up, while providing a separation between the displayed list and the filtering mechanism.

example usage

1. Create transformer, define filters

import React from 'react';
import { Transform } from 'react-reduce';

import ModeFilter from './filters/mode-filter.component';
import PriceFilter from './filters/price-filter.component';

export default () => {
    const products = [
        { mode: 'virtual', price: 10, name: 'product 1' },
        { mode: 'virtual', price: 50, name: 'product 2' },
        { mode: 'virtual', price: 500, name: 'product 3' },
        { mode: 'virtual', price: 1000, name: 'product 4' },
        { mode: 'real', price: 20, name: 'product 5' },
        { mode: 'real', price: 80, name: 'product 6' },
        { mode: 'real', price: 200, name: 'product 7' },
        { mode: 'real', price: 400, name: 'product 8' },
    ];

    return (
        <Transform
            toTransform={products}
            transformers={['modeFilter', 'priceFilter']}
        >
            {({ response: filteredProducts, refs, onChange }) => (
                <React.Fragment>
                    <ModeFilter ref={refs.modeFilter} onChange={onChange}/>
                    <PriceFilter ref={refs.priceFilter} onChange={onChange}/>
                    <pre>{JSON.stringify(filteredProducts, null, '\t')}</pre>
                </React.Fragment>
            )}
        </Transform>
    );
};

2. Define filters

Each filter should have a transform method, which will be fired (under the hood) after each filter change. The purpose of this method is to prepare a list according to the state of the filter.

Due to the fact that each filter can have a different form - I keep implementing the onChange function and preparing the state for self-implementation. It is important that the self-implemented onChange function should run the `onChange function passed in the props.

2.1. Example implementation of mode filter mechanism

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class ModeFilter extends Component {
    static propTypes = {
        onChange: PropTypes.func,
        defaultValue: PropTypes.string,
    };

    static defaultProps = {
        onChange: () => {},
        value: 'all',
    };

    state = ModeFilter.defaultProps;

    render() {
        return (
            <select
                value={this.state.value}
                onChange={event => this._onChange(event)}
            >
                <option value="all">all</option>
                <option value="virtual">virtual</option>
                <option value="real">real</option>
            </select>
        );
    }

    transform(list) {
        return (this.state.value === 'all') ? list : (
            list.filter(element => element.mode === this.state.value)
        );
    }

    _onChange(event) {
        const { value } = event.target;

        this.setState({ value }, () => this.props.onChange(value));
    }
}

2.2. Example implementation of price filter mechanism

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class PriceFilter extends Component {
    static propTypes = {
        onChange: PropTypes.func,
        defaultValue: PropTypes.string,
    };

    static defaultProps = {
        onChange: () => {},
        value: 'all',
    };

    state = ModeFilter.defaultProps;

    render() {
        return (
            <select
                value={this.state.value}
                onChange={event => this._onChange(event)}
            >
                <option value="all">all</option>
                <option value="less">price less than 100</option>
                <option value="greater">price greater than 100</option>
            </select>
        );
    }

    transform(list) {
        if (this.state.value === 'all') {
            return list;
        }

        if (this.state.value === 'less') {
            return list.filter(element => (element.price < 100));
        } else if (this.state.value === 'greater') {
            return list.filter(element => (element.price > 100));
        }
    }

    _onChange(event) {
        const { value } = event.target;

        this.setState({ value }, () => this.props.onChange(value));
    }
}
0.2.0

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago