首页 文章

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

提问于
浏览
1

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

在我的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 回答

  • 1

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

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

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

    render() 方法中, filter() 也会更加健壮 . 目前,如果事情不匹配,它们将被完全抛弃 .

    请参阅下面的示例 .

    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>
           
           
    <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
      }
    }
    

相关问题