在您键入时,React / Redux搜索过滤器更新应用程序状态

时间:2017-12-13 02:05:40

标签: reactjs redux

我正在尝试创建一个搜索过滤器,当您在输入字段中键入搜索查询时,应用程序状态会更新。到目前为止,在我的组件中,我能够查看初始应用程序状态。

在我的reducer中,我正在检查搜索查询是否与任何动物匹配 - 然后我相应地更新应用程序状态(通过过滤掉不匹配的对象)。检查似乎工作正常,但它不会呈现屏幕。

编辑: 它现在通过更新状态来缩小搜索范围但我需要一种方法来恢复应用程序状态,因为我从搜索字段中删除了字符。知道怎么样?

行动创作者:

export const FETCH_DATA = 'FETCH_DATA'
export function search(data){
    return {
        type: FETCH_DATA,
        payload: data
    }
}

减速机:

import { FETCH_DATA } from '../actions/index';
var _ = require('lodash');

const initialState = [
      {
        "animal": "Heron, giant"
      }, {
        "animal": "Lizard"
      }, {
        "animal": "Blesbok"
      }, {
        "animal": "Ibex"
      }, {
        "animal": "Pigeon, wood"
      }, {
        "animal": "Ground monitor"
      }
]

export default function(state = initialState, action){
    switch (action.type){
        case FETCH_DATA:
        const {payload} = action
            state = _.filter(state, function(o){
              return o.animal.toLowerCase().includes(payload.toLowerCase());
            })
            return state;
        default:
            return state;
    }

}

CombineReducer:

import { combineReducers } from 'redux';
import SearchReducer from './reducer_search';

const rootReducer = combineReducers({
  animals: SearchReducer
});

export default rootReducer;

组件:

import React, { Component } from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {search} from '../actions/index';

class Search extends Component {
    render() {
        //console.log(this.props.data)
        return (
            <div>
                <div className="form-group">
                    <input className="form-control" onChange={(e)=> this.props.search(e.target.value)} />
                </div>
                <div>
//conditional rendering
                    <ul>
                    {
                        this.props.data.filtered.length == 0 ? 
                        this.props.data.animals.map(item => {
                            return <li>{item.animal}</li>
                        }) :
                        this.props.data.filtered.map(item => {
                            return <li>{item.animal}</li>
                        })
                    }
                  </ul>
                </div>
            </div>
        );
  }
}

function mapStateToProps(state){
    return {data : state.animals}
}

//action creator
function mapDispatchToProps(dispatch) {
    return bindActionCreators({search}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Search);

1 个答案:

答案 0 :(得分:1)

Array.prototype.filter()排除任何不返回true的内容。

鉴于您当前的实施情况:如果您尝试搜索"Lizard";您的整个state将在"L"被删除,因为'L' === o.animal会在所有情况下返回false

我建议使用String.prototype.includes(),而不是使用===进行完全严格的比较。

filter()方法中的render()也会更强大。目前,如果事情不匹配,它们将被完全抛弃。

请参阅下面的示例。

class Search extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      animals: [
        {
          animal: 'Heron, giant'
        }, {
          animal: 'Lizard'
        }, {
          animal: 'Blesbok'
        }, {
          animal: 'Ibex'
        }, {
          animal: 'Pigeon, wood'
        }, {
          animal: 'Ground monitor'
        }
      ],
      query: false
    }
  }

  render() {

    return (
     <div>

       <div>
         <input placeholder="search" value={this.state.query || ''} onChange={(event) => this.setState({query: event.target.value})}/>
       </div>
       
       <br/>

       <div>
         <div>ANIMALS</div>
         {this.state.animals.filter((animal) => _.toLower(animal.animal).includes(_.toLower(this.state.query || ''))).map((animal) => <div>{animal.animal}</div>)}
       </div>

     </div>

    )
  }

}

ReactDOM.render(<Search/>, document.querySelector('#root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Redux解决方案:

// Dependencies.
import { FETCH_DATA } from '../actions/index' // Actions.
const _ = require('lodash') // Lodash.

const animals = [
  {
    "animal": "Heron, giant"
  }, {
    "animal": "Lizard"
  }, {
    "animal": "Blesbok"
  }, {
    "animal": "Ibex"
  }, {
    "animal": "Pigeon, wood"
  }, {
    "animal": "Ground monitor"
  }
]

// Initial State.
const initialState = {
  animals,
  filtered: animals
}

// Reducer.
export default function(state = initialState, action){
  switch (action.type){
    case FETCH_DATA:
      const {payload} = action
      const filtered = _.filter(state.animals, (o) => _.toLower(o.animal).includes(_.toLower(payload)))
      return {...state, filtered}
    default:
      return state
  }
}