ReactJs setState пропускает первую букву - PullRequest
0 голосов
/ 22 февраля 2019

Всякий раз, когда я что-то печатаю, строка поиска обновляет состояние, она пропускает первую букву.Например, если я пишу «asdf», он показывает только «sdf».

Я пробовал console.log перед этой строкой кода

this.props.newQuery(this.state.newSearchQuery);

и все былоработает нормально.

Пожалуйста, проверьте приведенный ниже код App.js и SearchBar.js

Спасибо

App.js

import React from 'react';

import SearchBar from './components/SearchBar';

class App extends React.Component {
  constructor(){
    super();

    this.state = {
      searchQuery: '',
      fetchedData: []
    };
  }

  newQuery(query){
    this.setState({
      searchQuery: query
    });
  }

  onSearch(){
    const userInput = this.state.searchQuery;

    if(userInput !== '' && userInput !== ' '){
      const API_KEY = `https://pokeapi.co/api/v2/pokemon/${userInput}`;

      fetch(API_KEY, {
        method: 'GET',
        headers: {
          Accept: 'application/json'
        }
      })
      .then(result => result.json())
      .then(data => this.setState({ fetchedData: data.results }));

      console.log('res', this.state.fetchedData);
    }
  }

  render(){
    return(
      <div className="App">
        <h2>Search Pokemos by Types</h2>
        <hr />
        <SearchBar onSearch={this.onSearch.bind(this)} newQuery={this.newQuery.bind(this)} />
      </div>
    );
  }
}

export default App;

SearchBar.js

import React from 'react';

class SearchBar extends React.Component {
    constructor(props){
        super(props);

        this.state = {
            newSearchQuery: '' //this blank value get executed first when i console.log
        }
    }
    searchInput(event){
        this.setState({
            newSearchQuery: event.target.value
        });

        this.props.newQuery(this.state.newSearchQuery);

        console.log(this.state.newSearchQuery); // if i log "asdf", state on top "newSearchQuery" skips the first letter, a and shows "sdf" only.
    }

    render(){
        return(
            <div className="input-group">
                <input onChange={this.searchInput.bind(this)} className="form-control" placeholder="[eg. Ditto, Cheri, etc]" />

                <button onClick={this.props.onSearch} className="btn btn-success">Search</button>
            </div>
        );
    }
}

export default SearchBar;

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Я немного сбит с толку относительно избыточного состояния между двумя компонентами.Я думаю, что я бы сделал (если бы я не использовал что-то вроде mobx), сохранив состояние родительского компонента и передав функции handleChange и handleSearch компоненту <Search />.Это выглядело бы примерно так ...

Я собрал для вас коды и коробки: https://codesandbox.io/s/n1ryz4rzwl

Компонент приложения

import React, { Component } from 'react';
import SearchBar from './components/SearchBar'

class App extends Component {
  constructor() {
    super()
    this.state = {
      searchQuery: '',
      fetchedData: []
    }
  }

  handleChangeQuery = event => this.setState({searchQuery: event.target.value})

  handleSearch = () => {
    const {searchQuery} = this.state,
      API_KEY = `https://pokeapi.co/api/v2/pokemon/${searchQuery}`;

    fetch(API_KEY, {
      method: 'GET',
      headers: {
        Accept: 'application/json'
      }
    })
    .then(result => result.json())
    .then(data => this.setState({ fetchedData: data.results }));
  }

  render() {
    const {searchQuery} = this.state
    return (
      <div className="App">
        <h2>Search Pokemos by Types</h2>
        <hr />
        <SearchBar
          value={searchQuery} 
          handleChangeQuery={this.handleChangeQuery} 
          handleSearch={this.handleSearch}  
        />

        // Show fetchedData results here

      </div>
    )
  }
}

export default App

Компонент SearchBar - Этот МОЖЕТ быть функциональным компонентом без сохранения состояния

import React from 'react'

const SearchBar = ({value, handleChangeQuery, handleSearch}) => {
  return (
    <div className="input-group">
      <input 
        onChange={handleChangeQuery} 
        value={value}
        className="form-control" 
        placeholder="[eg. Ditto, Cheri, etc]" 
      />
      <button onClick={handleSearch} className="btn btn-success">Search</button>
    </div>
  )
}

export default SearchBar

Причины странного пропущенного символа были описаны в других комментариях - как this.setState() можетбыть асинхроннымОднако, this.setState() имеет функцию обратного вызова, которую можно использовать для подтверждения изменения, если вы хотите проверить это.Это выглядит примерно так:

this.setState({key: value}, () => {
  // State has been set
  console.log(this.state.key)
})
0 голосов
/ 22 февраля 2019

console.log не регистрируется должным образом, потому что метод setState() не всегда выполняется как его вызванный.Согласно Документам

Обновления состояний могут быть асинхронными : поскольку this.props и this.state могут обновляться асинхронно, вам не следует полагаться на их значениядля расчета следующего состояния.

Поэтому, когда вы регистрируете это console.log(this.state.newSearchQuery); после setState, состояние фактически не изменяется, поэтому оно регистрирует неожиданное

...