React.js Автозаполнение с нуля - PullRequest
0 голосов
/ 09 ноября 2018

В рамках технического теста меня попросили написать автозаполнение ввода в React.Я сделал это, но теперь я хотел бы добавить функциональность навигации вверх и вниз по отображаемому списку с помощью клавиш со стрелками.Я сделал несколько обширных поисков и не нашел ничего конкретного для React, кроме пакетов npm.

Для ясности, я ищу что-то подобное, но для React: https://www.w3schools.com/howto/howto_js_autocomplete.asp

Все, что яв основном нужна функциональность кнопки со стрелкой, у меня все остальное работает нормально.

Приветствия

Вот пример, который я пробовал, но не смог работать.

export default class Example extends Component {
  constructor(props) {
    super(props)
    this.handleKeyDown = this.handleKeyDown.bind(this)
    this.state = {
      cursor: 0,
      result: []
    }
  }

handleKeyDown(e) {
    const { cursor, result } = this.state
    // arrow up/down button should select next/previous list element
    if (e.keyCode === 38 && cursor > 0) {
      this.setState( prevState => ({
        cursor: prevState.cursor - 1
      }))
    } else if (e.keyCode === 40 && cursor < result.length - 1) {
      this.setState( prevState => ({
        cursor: prevState.cursor + 1
      }))
    }
  }

  render() {
    const { cursor } = this.state

    return (
      <Container>
        <Input onKeyDown={ this.handleKeyDown }/>
        <List>
          {
            result.map((item, i) => (
              <List.Item
                key={ item._id }
                className={cursor === i ? 'active' : null}
              >
                <span>{ item.title }</span>
              </List.Item>
            ))
          }
        </List>
      </Container>
    )
  }
}

А вот мой код:

class Search extends Component {
  constructor(props) {
    super(props);
    this.state = {
      location: '',
      searchName: '',
      showSearch: false,
      cursor: 0
    };
  }

handleKeyPress = e => {
    const { cursor, searchName } = this.state;
    // arrow up/down button should select next/previous list element
    if (e.keyCode === 38 && cursor > 0) {
      this.setState(prevState => ({
        cursor: prevState.cursor - 1
      }));
    } else if (e.keyCode === 40 && cursor < searchName.length - 1) {
      this.setState(prevState => ({
        cursor: prevState.cursor + 1
      }));
    }
  };

 render() {
    const { searchName, location } = this.state;

    return (
      <div className="Search">
        <h1>Where are you going?</h1>
        <form id="search-form" onSubmit={this.handleSubmit}>
          <label htmlFor="location">Pick-up Location</label>
          <input
            type="text"
            id="location"
            value={location}
            placeholder="city, airport, station, region, district..."
            onChange={this.handleChange}
            onKeyUp={this.handleKeyUp}
            onKeyDown={this.handleKeyPress}
          />

          {this.state.showSearch ? (
            <Suggestions searchName={searchName} />
          ) : null}

          <button value="submit" type="submit" id="search-button">
            Search
          </button>
        </form>
      </div>
    );
  }

Код, который отображает список из API restful:

.then(res =>
  this.setState({
    searchName: res.data.results.docs.map(array => (
      <a href="#">
        <div
          key={array.ufi}
          className="locations"
        >
          {array.name}
        </div>
      </a>
    ))
  })
);

1 Ответ

0 голосов
/ 09 ноября 2018

Поскольку вы определяете функцию как handleKeyDown(e) {...}, контекст this не указывает на контекст экземпляра класса, контекст будет предоставлен onKeyDown (и я предполагаю, что window как this)

Итак, у вас есть 2 пути:

  1. объявите вашу функцию как handleKeyDown = (e) => {...}

  2. связать контекст handleKeyDown с экземпляром компонента, например onKeyDown={this.handleKeyDown.bind(this)}

Кроме того, не забывайте, что вам может потребоваться счетчик мод items.length, то есть когда вы нажмете и последний элемент уже выбран, он перейдет к первому элементу.

Ваше использование API с сохранением уценки в состояние просто ужасная вещь. У вас больше нет доступа к этим строкам, вместо этого сохраните их как простой массив. Передайте его туда, где вам нужно, и используйте его для создания jsx там.

Кроме того, вы вообще не используете курсор из своего состояния.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...