简体   繁体   English

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

[英]How to make a generic 'filter' Higher-Order Component in React.js?

I am making a Higher-Order Component in my React.js (+ Redux) app, to abstract the functionality to filter a list of elements with the string received from an input element. 我正在我的React.js(+ Redux)应用程序中制作一个高阶组件,以抽象该功能,以使用从输入元素接收的字符串过滤元素列表。

My filtering HOC is, 我的筛选HOC是

filter.js 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}
        />
      )
    }
  }
}

Right now, I am unable to access the filteredList as props.filteredList in the SearchResults component. 现在,我无法在SearchResults组件中以props.filteredList的形式访问filteredList。

The component to display the list is 显示列表的组件是

SearchResults.js 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

How do I go on about this? 我该怎么办?

EDIT: 编辑:

Adding the container component for greater clarity: 添加容器组件以提高清晰度:

SearchContainer.js 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)

Let's first think of components as a function that takes a props and returns a Virtual DOM. 首先,让我们将组件视为一个需要道具并返回虚拟DOM的函数。

Thus the SearchResult component takes these props: 因此,SearchResult组件采用以下道具:

  • filteredList filteredList
  • searchTerm 搜索词
  • setSearchTerm setSearchTerm

The higher-order-component created created by connect() provides these props: connect()创建的高阶组件提供了以下支持:

  • searchTerm 搜索词
  • currencyList currencyList

The Filter() higher-order component: Filter()高阶组件:

  • takes currencyList 需要currencyList
  • provides filteredList 提供filteredList

Therefore, you have to wire it like this so that each part receives the props it needs: 因此,您必须像这样进行连接,以便每个零件都能接收到所需的道具:

connect(...)FilterSearchResult connect(...)FilterSearchResult

It should look like this: 它看起来应该像这样:

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

Or if you use recompose : 或者,如果您使用recompose

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

export default enhance(SearchResult)

compose() wraps the components from right to left. compose()从右到左包装组件。 Therefore, the leftmost higher-order component becomes the outermost one. 因此,最左边的高阶成分成为最外面的成分。 This means the props will flow from left to right. 这意味着道具将从左向右流动。


Please note that state.searchTerm in FilterComponent#generateList should be this.props.searchTerm . 请注意, FilterComponent#generateList中的state.searchTerm应该是this.props.searchTerm

What is 'state.searchTerm' in your wrapper function? 包装函数中的“ state.searchTerm”是什么? I have a feeling you mean this.props.searchTerm. 我觉得您的意思是this.props.searchTerm。 Also, you don't need an empty constructor in es6 classes. 另外,在es6类中不需要空的构造函数。 Also, this is work better done by a selector in your mapstatetoprops on the container. 另外,最好通过容器上的mapstatetoprops中的选择器来完成此工作。

Edit: Also, you need to wrap the actual 'dumb' component, not the result of your connect call. 编辑:此外,您需要包装实际的“哑巴”组件,而不是连接调用的结果。 That way your redux store is connected to your Filter component and will be rerendered when you're store changes. 这样,您的redux存储将连接到Filter组件,并且在存储更改时将重新呈现。

generateList() is not reactive. generateList()不具有反应性。 It does not get triggered when the search term is changed. 更改搜索词时不会触发它。

SearchResults should be stateful and the container component. SearchResults应该是有状态的,并且是容器组件。 The list component should respond to change in the search term by receiving the search term as props. 列表组件应通过接收搜索词作为道具来响应搜索词的变化。 generateList should be the functionality of componentWillReceiveProps of the list component. generateList应该是列表组件的componentWillReceiveProps的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM