搜索栏可过滤带有超时的React中的表结果

时间:2018-08-30 18:25:37

标签: javascript reactjs timeout lodash semantic-ui-react

我正在使用语义React UI Search来过滤React中数据表组件的结果。如果搜索为空,则表应显示所有数据,如果搜索不为空,则表不显示任何数据或匹配结果。我的问题是,进行搜索时始终会出现“没有数据”的快速闪动。

原始搜索代码将结果显示为下拉列表,但我对其进行了修改以修改表。代码在下面。

class Page extends Component {
  resetComponent = () => this.setState({ isLoading: false, results: [], value: '' })

  handleSearchChange = (e, { value }) => {
    this.setState({ isLoading: true, value })

    setTimeout(() => {
      if (this.state.value.length < 1) return this.resetComponent()

      const re = new RegExp(_.escapeRegExp(this.state.value), 'i')
      const isMatch = result => re.test(result.name)

      this.setState({
        isLoading: false,
        results: _.filter(this.props.users, isMatch),
      })
    }, 200)
  }

  render() {
    const { users } = this.props
    const { value, results } = this.state
    const dataToShow = _.isEmpty(results) && !value ? users : results

    return (
      <Container>
        <Search
          open={false}
          loading={isLoading}
          onSearchChange={_.debounce(this.handleSearchChange, 500, { leading: true })}
          value={value}
          {...this.props}
        />
        <Table data={dataToShow} />
      </Container>
    )
  }
}

我认为const dataToShow = _.isEmpty(results) && !value ? users : results行是导致其闪烁的原因,但是我不知道如果不匹配,则不显示任何结果,如果为空,则不显示所有结果。

如何使此超时/反弹功能在桌子上正常工作?

如果我执行<Table data={results} />,则反跳有效,但表在初始加载时不会显示所有数据。

1 个答案:

答案 0 :(得分:1)

实际上是在设置this.setState({ isLoading: true, value })时,组件自更改状态以来将重新呈现。发生这种情况时,此行:

const dataToShow = _.isEmpty(results) && !value ? users : results

实际上将显示results-因为尽管结果为空,但您确实输入了一个值。这就是为什么您绑定到结果但它们为空时会得到“无数据”的原因。

在此尝试:

const dataToShow = _.isEmpty(results) && !value ? users : this.state.isLoading ? users : results

在键入值时,它应该继续显示users,并且一旦完成加载,它应该更改为结果。

但是问题是(这就是为什么我建议使用微调器的简单方法)现在您将显示结果...然后在新搜索中,您将返回到用户,然后在加载完成后再次返回结果

<Table>为真的情况下,我根本不会显示this.state.isLoading,如果显示的是...,则显示一些“旋转器”,例如:

    class Page extends Component {
      resetComponent = () => this.setState({ isLoading: false, results: [], value: '' })
    
      handleSearchChange = (e, { value }) => {
        setTimeout(() => {
           this.setState({ isLoading: true, value })

           if (this.state.value.length < 1) return this.resetComponent()
           const re = new RegExp(_.escapeRegExp(this.state.value), 'i')
           const isMatch = result => re.test(result.name)
           this.setState({
              isLoading: false,
              results: _.filter(this.props.users, isMatch),
           })
        }, 200)
	  }

      render() {
        const { users } = this.props
        const { value, results } = this.state
        const dataToShow = _.isEmpty(results) && !value ? users : results
    
        return (
          <Container>
            <Search
              open={false}
              loading={isLoading}
              onSearchChange={_.debounce(this.handleSearchChange, 500, { leading: true })}
              value={value}
              {...this.props}
            />
            {this.state.isLoading && <Spinner />}
            {!this.state.isLoading && <Table data={dataToShow} />}
          </Container>
        )
      }
    }

但是,由于我们不同意这种UX模式,因此这里有另一个建议:

跟踪先前的结果并不断显示它们,直到新状态发生变化并产生新结果为止:

class Page extends Component {
  constructor (props) {
     super(props)
     this.state = {
        isLoading: false,
        results: [],
        oldResults: this.prop.users || [],
        value: ''
     }
   }
	
  resetComponent = () => this.setState({ isLoading: false, results: [], oldResults: this.prop.users || [], value: '' })

  handleSearchChange = (e, { value }) => {
    setTimeout(() => {
    this.setState({ isLoading: true, value })

    if (this.state.value.length < 1) return this.resetComponent()
			 
    const re = new RegExp(_.escapeRegExp(this.state.value), 'i')
    const filteredResults = _.filter(this.props.users, result => re.test(result.name))
       this.setState({
         isLoading: false,
         results: filteredResults,
         oldResults: filteredResults
       })
    }, 200)
  }

  render() {
    const { users } = this.props
    const { value, results } = this.state
    const dataToShow = (_.isEmpty(results) && !value) || this.state.isLoading ? oldResults : results
    return (
      <Container>
        <Search
          open={false}
          loading={isLoading}
          onSearchChange={_.debounce(this.handleSearchChange, 500, { leading: true })}
          value={value}
          {...this.props}
        />
	<Table data={dataToShow} />
      </Container>
    )
  }
}