如何实现React Redux搜索和复选框过滤器

时间:2018-09-20 18:14:45

标签: react-redux

我正在尝试在我的react项目中实现搜索/过滤器,但似乎无法正确实现。 Screenshot

这是用户应该能够做的:

  1. 按文本过滤
  2. 使用复选框按位置过滤
  3. 或按职位类别过滤

我现在所拥有的是我可以按文本和复选框进行过滤,但是我希望用户能够按文本进行搜索,例如“达拉斯”,“信息技术”,“销售”,然后进一步过滤使用类别或位置,使用文本搜索返回的数据。

这是我的设置:

  1. 按文本搜索使用精简器按搜索文本过滤数组
  2. 选中位置或类别复选框将值存储在类别或关键字数组中
  3. 在组合减速器文件中,我过滤了商店中的jobs数组并使用重新选择记忆。

我在搜索文本和复选框功能上有一些小故障。按位置过滤复选框功能本身可以正常工作;但是,当选中一个复选框并输入搜索文本时,该复选框将被取消选中。我希望当在输入字段中输入文本时,该复选框仍被选中并显示在窗口中。

我是新手,将非常感谢您对此功能的任何帮助,建议或更好的方法。

SEARCHFORM.JS:

import React, {Component} from 'react';
//import {FormGroup, FormControl, InputGroup} from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { searchJobs, getJobs } from '../actions/jobaction';
import {selectKeywordCity,deselectKeywordCity} from '../actions/selectDeselectCityAction';
import {selectKeywordCategory,deselectKeywordCategory} from '../actions/selectDeselectCategoryAction';

class Search extends Component{
    constructor(props){
        super();
        this.state = {
            keyword:'',
            checked:[]
        };
        this.handleChk = this.handleChk.bind(this);
    }

    handleInput = (event) => {
        this.setState({
            keyword: event.target.value
        });
        this.props.searchJobs(this.state.keyword);
    }

/*  handleSearch = (event) => {
        event.preventDefault();
        this.props.getJobs(this.state.keyword);
    } */

    clearForm = () => {
        this.inputSearch.value = "";
        this.setState({
            keyword: this.inputSearch.value
        });
        this.props.getJobs();
    }

    handleChk = (e, keyword, type) => {
        if(type==='city'){
            e.target.checked ? this.props.selectKeywordCity(keyword) : this.props.deselectKeywordCity(keyword);
        }else if(type==='category'){
            e.target.checked ? this.props.selectKeywordCategory(keyword) : this.props.deselectKeywordCategory(keyword);
        }

    }

    //Render Cities
    renderCities(data){
        if(data){
            const cities = Object.keys(data).map(el => {
                    return data[el].city
                }).sort()
                .reduce((city,name) => {
                    const cityCount = city[name] ? city[name] + 1 : 1;

                    return{
                        ...city, [name]:cityCount,
                    };

                },{});
            return Object.keys(cities).map((keyname, index) => {
                    return (
                        <li key={keyname}>
                            <input type="checkbox" 
                            onChange={e=>this.handleChk(e,keyname,'city')}
                            className="chkbox"
                        />
                                {keyname}
                            <span className="pull-right">{cities[keyname]}</span> 
                        </li>)
                    })
        }else{
                return("nada")
        }
    }

    //Render Job Categories

    renderCategories(data){
        if(data){
            const categories = Object.keys(data).map(el => {
                    return data[el].category
                }).sort()
                .reduce((category,name) => {
                    const categoryCount = category[name] ? category[name] + 1 : 1;

                    return{
                        ...category, [name]:categoryCount,
                    };

                },{});
            return Object.keys(categories).map((keyname, index) => {
                    return (
                        <li key={keyname}>
                            <input type="checkbox" 
                            onChange={e=>this.handleChk(e,keyname,'category')}
                            className="chkbox"
                        />
                                {keyname}
                            <span className="pull-right">{categories[keyname]}</span> 
                        </li>)
                    })
        }else{
                return("nada")
        }
    }

    render(){

        let closeBtn = null;

        if(this.state.keyword){
            closeBtn = (<i className="fa fa-times" onClick={this.clearForm}></i>);
        }

        return(
            <div>
                <div className="side-search">
                    <i className="fa fa-search"></i>
                    <input type="text" 
                            placeholder="Keyword Search" 
                            ref={el => this.inputSearch = el}
                            onChange={this.handleInput}
                            value={this.state.keyword}
                    />

                    {closeBtn}
                </div>
                <div className="chk_boxes">
                    <h4>Location</h4>
                    <ul>
                        {
                            this.renderCities(this.props.jobs)
                        }
                    </ul>
                </div>
                <div className="chk_boxes">
                    <h4>Category</h4>
                    <ul>
                        {
                            this.renderCategories(this.props.jobs)
                        }
                    </ul>
                </div>
            </div>
            )
    }
}

function mapStateToProps(state){
    return{
        jobs: state.jobs.jobs
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({searchJobs, 
                               getJobs,
                               selectKeywordCity,
                               deselectKeywordCity,
                               selectKeywordCategory,
                               deselectKeywordCategory},
                               dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(Search);

任务:

import axios from 'axios';
const FETCH_URL = 'http://localhost:3006';

/* GET ALL JOB LISTINGS */
export function getJobs(){
    return function(dispatch){
        axios.get(`${FETCH_URL}/jobs`)
        .then(function(response){
            dispatch({type:'GET_JOBS',payload:response.data})
        }).catch(function(err){
            dispatch({type:'GET_JOBS_ERROR', payload:err});
        })
    }
}

/* GET ALL JOB LISTINGS */
export function searchJobs(keyword){
    return function(dispatch){
        axios.get(`${FETCH_URL}/jobs?q=${keyword}`)
        .then(function(response){
            dispatch({type:'SEARCH_JOBS',payload:response.data})
        }).catch(function(err){
            dispatch({type:'SEARCH_JOBS_ERROR', payload:err});
        })
    }
}

工作表缩减器:

export function Listings (state={}, action){
    switch(action.type){
        case 'GET_JOBS':
        return{...state, jobs:action.payload}
        case 'SEARCH_JOBS':
        return{...state, jobs:action.payload}
        default:
        return state;
    }
}

SELECTDESELECT(复选框)减少器:

const INITIAL_STATE = {
    keywords:[]
}
export function filterCity(state=INITIAL_STATE, action){
    switch(action.type){
        case 'SELECT_CITY':
        return{
            keywords:[...state.keywords, action.payload]
        }
        case 'DESELECT_CITY':
        const currentKeywordToDelete = [...state.keywords];
        const indexOfKeyword = currentKeywordToDelete.findIndex(function(keyword){
            return keyword === action.payload
        });
        return{
            keywords:[...state.keywords.slice(0,indexOfKeyword), ...currentKeywordToDelete.slice(indexOfKeyword+1) ]
        }
        default:
            return state;
    }
}

COMBINEREDUCER:

    import {combineReducers} from 'redux';
import {createSelector} from 'reselect'; 
import {Listings} from './listingsReducer';
import {filterCity} from './select-deselect-city';
import {filterCategory} from './select-deselect-category';

const reducer = combineReducers({
    jobs: Listings,
    keywords: filterCity,
    category: filterCategory
});

export const selectJobList = (state) => state.jobs.jobs;
export const selectCities = (state) => state.keywords.keywords;
//export const selectCategories = (state) => state.categories.categories;

export  const selectFilteredJobs = createSelector(
    selectJobList,selectCities,
    (jobs,cities) => {

        if(cities && cities.length > 0){
            const filteredData = Object.keys(jobs)
                .filter(key => cities.includes(jobs[key].city))
                .reduce((obj, key) => {
                    return [...obj, {...jobs[key]}]
                  }, []);
                //console.log(filteredData);
            return filteredData;
        }else{
            return jobs
        }
    } 
)

export default reducer;

JSON数据:

{
    "jobs": [
        {
          "id": 1,
          "title": "Financial Analyst II",
          "description": "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. .",
          "category": "Sales",
          "dept": "Finance",
          "date": "07/11/2018",
          "experience": ["Bachelors Degree","Five years of sales experience"],
          "city": "Dallas",
          "state":"Texas",
          "salary": "10,000"
       },
       {
          "id": 2,
          "title": "Application Support Speacialist",
          "description": "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.",
          "category": "Information Technology",
          "dept": "Accounting",
          "date": "07/10/2018",
          "experience": ["Bachelors Degree","Two years of sales experience"],
          "city": "Dallas",
          "state":"Texas",
          "salary": "20,000"
       }
}

0 个答案:

没有答案