【问题标题】:ReactJs setState skips first letterReactJs setState 跳过第一个字母
【发布时间】:2019-02-22 19:49:30
【问题描述】:

每当我输入内容时,搜索栏都会更新状态,它会跳过第一个字母。例如,如果我写“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;

搜索栏.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;

【问题讨论】:

  • 不发图片,发真实代码。
  • 添加了代码。谢谢
  • 您的意思是console.log(this.state.newSearchQuery); 记录错误?
  • 是的,它会跳过字符串的第一个字母。例如,当它应该记录“USA”时,它只通过跳过“U”来记录“SA”。
  • 要知道,setState 在第二个参数中有一个回调,它将在状态更新后发生。 setState({ name: "Michael" }, () =&gt; console.log(this.state));

标签: javascript reactjs setstate


【解决方案1】:

console.log 未按预期记录,因为 setState() 方法并不总是在调用时执行。根据Docs

状态更新可能是异步的:因为this.propsthis.state 可能会异步更新,所以您不应依赖它们的值来计算下一个状态。

因此,当您在 setState 之后记录此 console.log(this.state.newSearchQuery); 时,状态实际上并没有改变,这就是它意外记录的原因

【讨论】:

  • 但是当我获取数据时,第一个字母也丢失了。例如,如果我搜索“ditto”以从 pokeapi 获取,那么它会搜索“ditt”而不是“ditto”。
  • @Najam Khan 在.then 回调中使用console.log()。如果你能给我codepen,我会尝试解决这个问题
【解决方案2】:

我对这两个组件之间的冗余状态有点困惑。我想我会做的(如果我没有使用类似 mobx 的东西)是保持父组件上的状态并将 handleChangehandleSearch 函数传递给 &lt;Search /&gt; 组件。它看起来像......

我为你整理了一个密码箱:https://codesandbox.io/s/n1ryz4rzwl

APP 组件

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

其他 cmets 已经描述了奇怪的缺失字符背后的原因 - 因为 this.setState() 可能是异步的。但是,this.setState() 确实有一个回调函数,如果你想测试它,可以使用它来确认更改。它看起来像:

this.setState({key: value}, () => {
  // State has been set
  console.log(this.state.key)
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 2014-07-20
    • 1970-01-01
    • 2011-03-22
    • 2012-11-24
    • 1970-01-01
    相关资源
    最近更新 更多