Реагировать на использование useState Hook с контролируемым компонентом ввода - PullRequest
0 голосов
/ 21 апреля 2020

В моем приложении есть компонент управляемого класса, который я хочу превратить в функциональный компонент, использующий хуки. Раньше код работал нормально, устанавливая event.target.value на входе и устанавливая состояние searchTerm в качестве текущего значения. Однако после рефакторинга с помощью ловушек я заметил проблему со значением состояния searchTerm, состоящим из букв перед каждым event.target.value. Например, если я наберу «Джокер» в строке ввода, используя setSearchTerm(e.target.value), я получу состояние searchTerm как «Шутка», а не «Джокер», пока не вызову другое событие, нажав клавишу. Я не уверен, почему это происходит, потому что когда я делал это с компонентом класса, установка this.state.searchTerm в e.target.value достигла бы желаемой цели. Раньше, если бы я набрал «Джокер» в поле ввода, состояние searchTerm на самом деле было бы «Джокер». Любая помощь с этим будет принята с благодарностью. Спасибо!

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);

Console.log(e.target.value); до и после строки setSearchTerm оба возвращают правильное значение; однако, console.log(searchTerm); до и после строки setSearchTerm оба возвращают неправильное значение, которое является одним триггером события позади.

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Вам необходимо использовать useEffect для отслеживания изменения searchTerm:

useEffect(() => {
    // This will be called after searchTerm has been updated
    if (!searchTerm) return;
    clearTimeout(timeOut.current);
    timeOut.current = setTimeout(() => {
        searchMovies(searchTerm);
    }, 500);
}, [searchTerm]);

const doSearch = e => {
    // Just update the state, and let useEffect handle it
    setSearchTerm(e.target.value);
}
0 голосов
/ 21 апреля 2020
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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...