简体   繁体   中英

How do I do search autocomplete with React and Redux?

I have a component called Home that looks like:

  render () {
    const clips = ObjectPath.get(this.props, 'search.data.clips.results', [])

    return (
      <div className='search__container right-content-wrapper'>
        <SearchInput
          value={this.props.autocomplete.query.q}
          placeholder='Search all the Vidys'
          status={this.props.autocomplete.status}
          hints={this.props.autocomplete.data}
          onType={this.props.onAutocomplete}
          onSubmit={this.props.onSearch}
        />

        <SearchResults
          results={clips}
          location={this.props.location}
          status={this.props.search.status}
        />
      </div>
    )
  }

My SearchInput looks like:

  render () {
    const { value, hints, status } = this.props
    const hasResults = hints.length
    const areResultsVisible = hasResults && !this.state.hideAutocompleteResults && this.state.hasFocus

    return (
      <div className= {`search-input__component ${status}`}>

        {this.props.showLogo && (
          <a href="javascript:void(0);" className="logo-on-search"></a>
        )}

        <div className='input'>
          <input
            type='text'
            className='input-field'
            value={value}
            placeholder={this.state.placeholder}
            onFocus={::this.onFocus}
            onBlur={::this.onBlur}
            onKeyUp={::this.onKeyUp}
            onKeyDown={::this.hanleArrowKeys}
            onChange={::this.onChange}
          />
        </div>
        <button className="btn emoji"></button>
        <button className='btn submit' onClick={() => this.onSubmit()}></button>

        {(() => {
          if (!areResultsVisible && false) return

          const springConfig = {
            stiffness: 600,
            damping: 30
          }

          return <StaggeredMotion
            defaultStyles={hints.map((item) => ({ x: -10, o: 0, z: 1.1 }))}
            styles={(prevInterpolatedStyles) => prevInterpolatedStyles.map((_, i) => (
              i === 0
                ? {
                  o: spring(1, springConfig),
                  x: spring(1, springConfig),
                  z: spring(1, springConfig)
                }
                : {
                  o: spring(prevInterpolatedStyles[i - 1].o, springConfig),
                  x: spring(prevInterpolatedStyles[i - 1].x, springConfig),
                  z: spring(prevInterpolatedStyles[i - 1].z, springConfig)
                }
            ))}
          >
            {(styles) => (
              <div className='hints'>
                {styles.map((style, i) => (
                  <div
                    key={i}
                    className={`hint${i === this.state.hintSelection ? ' selected' : ''} ${hints[i].type}`}
                    onClick={() => this.onHintClick(hints[i])}
                    onMouseEnter={() => this.setState({ hintSelection: i })}
                    style={{
                      transform: `translateX(${style.x}px)`,
                      opacity: style.o
                    }}
                  >
                    <div className='hint-content'>
                      <div className='hint-title'>{this.highlightMatch(hints[i])}</div>
                      {(() => hints[i].type !== 'phrase' && <div className='hint-type'>{hints[i].type}</div>)()}
                    </div>
                  </div>
                ))}
              </div>
            )}
          </StaggeredMotion>
        })()}
      </div>
    )
  }

So I realize that I need to restructure a ton of stuff, so I'm looking for general guidance more than specific help. I'm relatively new to React and redux , so I may not understand it all. I feel like I somehow need to set up a connect in the SearchInput to do the actual search and autocomplete. Any ideas?

The SearchInput component should make an ajax request on each change of the input tag (in the onChange function of the input tag). In the the ajax's callback function, the new data (the new hints) should pass to a Redux action for updating the store with that data. The store's update will trigger re-render of the components with the new hints as new props from the store.

The search text itself should be stored in the component's state using the setState function in the onChange function of the input tag. This will allow the search's ajax request (after clicking on the search button and triggering an event function with that ajax request) to get the text input as simple state variable.

The same architecture should be used for updating the search results after clicking on the search button.

Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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