带有受控输入组件的useState Hook问题

问题描述 投票:0回答:1

我的应用程序中有一个受控类组件,我想变成一个利用钩子的功能组件。以前,通过在输入中设置event.target.value并将searchTerm的状态设置为该当前值,代码可以正常工作。但是,由于使用了挂钩进行重构,因此我注意到searchTerm状态值是每个event.target.value之前的字母的问题。例如,如果我在输入栏中键入“ Joker”,则使用setSearchTerm(e.target.value)将得到searchTerm状态为“ Joke”而不是“ Joker”,直到我通过按下一个键导致另一个事件为止。我不确定为什么会这样,因为当我使用类组件执行此操作时,将this.state.searchTerm设置为e.target.value会达到预期的目标。如果在输入字段中输入“ Joker”之前,searchTerm状态实际上是“ Joker”。任何帮助,将不胜感激。谢谢!

import React, { useState, useRef } from 'react';
import './SearchBar.styles.scss';
import FontAwesome from 'react-fontawesome';
import {connect} from 'react-redux';
import {searchMovies} from '../../redux/redux-home/home.actions';

const SearchBar = ({ searchMovies }) => {
    const [searchTerm, setSearchTerm] = useState('');
    // constructor(){
    //     super();
    //     this.state={
    //         searchTerm: ''
    //     }
    // }

    const timeOut = useRef(null);

    const doSearch = e => {
        clearTimeout(timeOut.current);
        setSearchTerm(e.target.value);
        // this.setState({[e.target.name]: e.target.value});

        timeOut.current = setTimeout(() => {
            searchMovies(searchTerm);
        }, 500);
    }
    return(
        <div className="searchbar">
            <div className="searchbar-content">
                <FontAwesome className="fa-search" name="search" size="2x"/>
                <input type="text" placeholder="Movie" autoComplete="off" onChange={doSearch} value={searchTerm}/>
            </div>
        </div>
    );
}
const mapDispatchToProps = dispatch => ({
    searchMovies: search => dispatch(searchMovies(search))
});

export default connect(null, mapDispatchToProps)(SearchBar);
reactjs react-hooks react-state use-state
1个回答
0
投票
function App() {
  const [value, setValue] = useState('');

  const timeOut = useRef(null);

  const change = (e) => {
    clearTimeout(timeOut.current);
    setValue(e.currentTarget.value)
    timeOut.current = setTimeout(() => {
      //see the diffetrence here
       console.log('hello', value, e.currentTarget.value)
  }, 500);
    console.log(e.target.value)
  }
  return (
    <div className="App">
      <input onChange={change} value={value} />
    </div>
  );
}

import React, { useState, useRef } from 'react';
import './SearchBar.styles.scss';
import FontAwesome from 'react-fontawesome';
import {connect} from 'react-redux';
import {searchMovies} from '../../redux/redux-home/home.actions';

const SearchBar = ({ searchMovies }) => {
    const [searchTerm, setSearchTerm] = useState('');
    // constructor(){
    //     super();
    //     this.state={
    //         searchTerm: ''
    //     }
    // }

    const timeOut = useRef(null);

    const doSearch = e => {
        clearTimeout(timeOut.current);
        setSearchTerm(e.target.value);
        // this.setState({[e.target.name]: e.target.value});

        timeOut.current = setTimeout(() => {
         // -----------------------------------
         console.log(searchTerm, e.currentTarget.value)
            searchMovies(searchTerm);
        }, 500);
    }
    return(
        <div className="searchbar">
            <div className="searchbar-content">
                <FontAwesome className="fa-search" name="search" size="2x"/>
                <input type="text" placeholder="Movie" autoComplete="off" onChange={doSearch} value={searchTerm}/>
            </div>
        </div>
    );
}
const mapDispatchToProps = dispatch => ({
    searchMovies: search => dispatch(searchMovies(search))
});

export default connect(null, mapDispatchToProps)(SearchBar);

0
投票

您可以复制e.target.value并在以后的setTimeout回叫中使用:

const doSearch = e => {
    clearTimeout(timeOut.current);
    setSearchTerm(e.target.value);
    // Deep copy
    const value = e.target.value.slice();       
    timeOut.current = setTimeout(() => {
        searchMovies(value);
    }, 500);
}
© www.soinside.com 2019 - 2024. All rights reserved.