如何在React.js中创建通用的“过滤器”高阶组件?

时间:2016-07-23 13:22:34

标签: javascript reactjs redux

我在我的React.js(+ Redux)应用程序中创建一个高阶组件,以抽象使用从输入元素接收的字符串过滤元素列表的功能。

我的过滤HOC是,

filter.js

import React, { Component } from 'react'

export default function Filter(FilteredComponent) {
  return class FilterComponent extends Component {
    constructor(props)  {
      super(props)      
    }

    generateList() {
      if (this.props.searchTerm !== undefined)  {
        let re = new RegExp(state.searchTerm,'gi')
        return this.props.currencyList.filter((c) => c.match(re))
      }
      else {
        return this.props.currencyList
      }
    }

    render() {
      return (
        <FilteredComponent
          filteredList={this.generateList()}
          {...this.props}
        />
      )
    }
  }
}

目前,我无法在SearchResults组件中将propList作为props.filteredList访问。

显示列表的组件是

SearchResults.js

import React from 'react'

const SearchResults = (props) => {
  const listData = props.filteredList.map (item => <div>{item}</div>)

  return (
    <div>
      Here are the search results.
      <br />
      <input
        type="text"
        value={props.searchTerm}
        onChange={props.setSearchTerm}
      />
      {listData}
    </div>   ) }

export default SearchResults

我如何继续这个?

编辑:

添加容器组件以获得更清晰:

SearchContainer.js

import {connect} from 'react-redux'
import SearchResults from '../components/SearchResults'
import * as a from '../actions'
import Filter from '../enhancers/filter'

const getSearchTerm = (state) => (state.searchTerm === undefined) ? '' : state.searchTerm

const mapStateToProps = (state) => {
  return  {
    searchTerm: getSearchTerm(state),
    currencyList: state.currencyList
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    setSearchTerm: (e) => {
      dispatch(a.setSearchTerm(e.target.value))
    }
  }
}

const SearchResultsContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(SearchResults)

export default Filter(SearchResultsContainer)

3 个答案:

答案 0 :(得分:2)

让我们首先将组件视为一个带有道具并返回虚拟DOM的函数。

因此,SearchResult组件采用这些道具:

  • filteredList
  • SEARCHTERM
  • setSearchTerm

connect()创建的高阶组件提供了这些道具:

  • SEARCHTERM
  • currencyList

Filter()高阶组件:

  • 采用currencyList
  • 提供filteredList

因此,您必须像这样连线,以便每个部分都能获得所需的道具:

  

connect(...)FilterSearchResult

它应该是这样的:

export default connect(...)(Filter(SearchResult))

或者如果您使用recompose

const enhance = compose(connect(...), Filter)

export default enhance(SearchResult)

compose()从右到左包装组件。因此,最左边的高阶分量成为最外面的分量。这意味着道具将从左向右流动。

请注意state.searchTerm中的FilterComponent#generateList应为this.props.searchTerm

答案 1 :(得分:1)

你的包装函数中的'state.searchTerm'是什么?我有一种感觉,你的意思是这个.props.searchTerm。此外,在es6类中不需要空构造函数。此外,这可以通过容器中mapstatetoprops中的选择器更好地完成。

编辑: 此外,您需要包装实际的“哑”组件,而不是连接调用的结果。这样您的redux商店就会连接到您的Filter组件,并在您进行商店更改时重新呈现。

答案 2 :(得分:-1)

generateList()不是被动的。更改搜索词时不会触发它。

SearchResults应该是有状态的容器组件。列表组件应通过将搜索词作为道具来响应搜索词中的更改。 generateList应该是列表组件的componentWillReceiveProps的功能。