反应输入字段记录空字符串作为第一个按键

时间:2018-06-28 16:33:14

标签: javascript reactjs

我不确定自己在做什么错,但是我有一个输入字段,用于输入搜索词并尝试根据搜索词过滤结果。问题是传递的第一个值是一个空字符串,此后每次按键输入都会偏移一个项目。例如,如果我键入“ sea”,它将把搜索词更新为“ se”。然后,当我尝试删除该值时,它会向另一个方向偏移,因此删除“ se”以“ s”结尾,无法删除。

(以下是正在进行的应用程序的链接:https://vibrant-yonath-715bf2.netlify.com/allpokemon。完整的搜索功能尚无法使用。对此我很陌生。)

import React, { Component } from 'react';

import Pokemon from './Pokemon';

class PokemonList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      pokemonList: [],
      searchTerm: '',
      fetched: false,
      loading: false
    };

    this.updateResults = this.updateResults.bind(this);
  }
  componentWillMount() {
    this.setState({
      loading: true
    });
    fetch('https://pokeapi.co/api/v2/pokemon?limit=151')
      .then(res => res.json())
      .then(response => {
        this.setState({
          pokemonList: response.results,
          loading: true,
          fetched: true
        });
      });
  }

  handleSearchTermChange = (
    event: SyntheticKeyboardEvent & { target: HTMLInputElement }
  ) => {
    this.setState({ searchTerm: event.target.value });
    this.updateResults();
  };

  updateResults() {
    const filteredList = this.state.pokemonList.filter(
      pokemon =>
        pokemon.name.toUpperCase().indexOf(this.state.searchTerm.toUpperCase()) >= 0
    );
    console.log(this.state.searchTerm);
    this.setState({
      pokemonList: filteredList
    });
  }

  render() {
    const { fetched, loading, pokemonList } = this.state;
    let content;
    if (fetched) {
      content = (
        <div className="flex-grid">
          {pokemonList.map((pokemon, index) => (
            <Pokemon key={pokemon.name} id={index + 1} pokemon={pokemon} />
          ))}
        </div>
      );
    } else if (loading && !fetched) {
      content = <p> Loading ...</p>;
    } else {
      content = <div />;
    }
    return (
      <div>
        <input
          onChange={this.handleSearchTermChange}
          value={this.state.searchTerm}
          type="text"
          placeholder="Search"
        />
        {content}
      </div>
    );
  }
}

export default PokemonList;

2 个答案:

答案 0 :(得分:1)

setState是异步的,因此调用this.state.searchTerm时不会更新updateResults。您可以例如而是在渲染中过滤数组。

示例

class App extends Component {
  state = {
    pokemonList: [
      { name: "pikachu" },
      { name: "bulbasaur" },
      { name: "squirtle" }
    ],
    searchTerm: ""
  };

  changeSearchTerm = event => {
    this.setState({ searchTerm: event.target.value });
  };

  render() {
    const { pokemonList, searchTerm } = this.state;
    const filteredList = pokemonList.filter(pokemon =>
      pokemon.name.toUpperCase().includes(searchTerm.toUpperCase())
    );

    return (
      <div>
        <input value={searchTerm} onChange={this.changeSearchTerm} />
        {filteredList.map(pokemon => <div>{pokemon.name}</div>)}
      </div>
    );
  }
}

答案 1 :(得分:0)

我认为问题在于您致电this.updateResults(); 然后调用this.setState({ searchTerm: event.target.value });而不是对setState使用回调函数。

例如:

this.setState({ searchTerm: event.target.value }, () => this.updateResults());

希望我做对了。

更新:

我还在您的代码中看到了许多问题,例如,为什么用过滤列表更新列表?您不需要这样做:

this.setState({
  pokemonList: filteredList
});

您无需仅更新状态中的结果,而只需要呈现已过滤的列表... ...意味着您的状态将保留在原始列表中,也将包含已过滤的value,仅在呈现时您传递已过滤的列表..