使用受控输入组件反应 useState Hook 问题
React useState Hook issue with controlled input component
我的应用程序中有一个受控的 class 组件,我想将其变成一个使用挂钩的功能组件。之前,通过在输入中设置 event.target.value
并将 searchTerm
的状态设置为当前值,代码可以正常工作。然而,自从用钩子重构后,我注意到 searchTerm
状态值是每个 event.target.value
之前的字母的问题。例如,如果我在输入栏中键入 "Joker",使用 setSearchTerm(e.target.value)
,我会得到 searchTerm 状态为 "Joke" 而不是 "Joker",直到我通过点击钥匙。我不确定为什么会这样,因为当我使用 class 组件执行此操作时,将 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);
Console.log(e.target.value);
在setSearchTerm
行前后都是return的正确值;但是,setSearchTerm
行前后的 console.log(searchTerm);
都是 return 不正确的值,这是一个事件触发的原因。
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);
您需要使用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);
}
我的应用程序中有一个受控的 class 组件,我想将其变成一个使用挂钩的功能组件。之前,通过在输入中设置 event.target.value
并将 searchTerm
的状态设置为当前值,代码可以正常工作。然而,自从用钩子重构后,我注意到 searchTerm
状态值是每个 event.target.value
之前的字母的问题。例如,如果我在输入栏中键入 "Joker",使用 setSearchTerm(e.target.value)
,我会得到 searchTerm 状态为 "Joke" 而不是 "Joker",直到我通过点击钥匙。我不确定为什么会这样,因为当我使用 class 组件执行此操作时,将 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);
Console.log(e.target.value);
在setSearchTerm
行前后都是return的正确值;但是,setSearchTerm
行前后的 console.log(searchTerm);
都是 return 不正确的值,这是一个事件触发的原因。
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);
您需要使用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);
}