【发布时间】:2020-08-17 12:12:34
【问题描述】:
我为在线练习制作了一个基本的电话簿应用程序,可让您将人们的姓名和电话号码保存到电话簿中。还有一个搜索输入,可让您根据名称过滤结果。一切正常,但是,我无法弄清楚的一件奇怪的事情是过滤器总是延迟一个字符,当用户在搜索栏中输入字符时状态不会立即更新?
例如:
如果我在搜索中输入“J”,它将过滤“”
如果我然后输入“a”,那么现在“Ja”在搜索栏中,它将过滤“J”
如果我然后退格“a”,那么现在“J”在搜索栏中,它将过滤“Ja”
等等……过滤器总是落后一步。
我是新来的国家,似乎无法解决它。谁能帮我吗?谢谢。 (另外,如果对我的代码有任何其他建设性的批评可以改进它,我非常开放和欣赏)
我的代码:
const phonebook = [
{
id: 1,
details: {
name: 'Jim',
number: '55 748 192'
}
},
{
id: 2,
details: {
name: 'Jason',
number: '55 111 192'
}
},
{
id: 3,
details: {
name: 'Jonesy',
number: '55 983 122'
}
},
{
id: 4,
details: {
name: 'Jack',
number: '0408 729 000'
}
},
]
const App = (props) => {
const [bookData, setBookData] = useState(props.props)
const [newName, setNewName] = useState('')
const [newNumber, setNewNumber] = useState('')
const [theFilter, setTheFilter] = useState('')
const [namesToShow, setNamesToShow] = useState(bookData.map(person => person.details))
const [errorMessage, setErrorMessage] = useState('')
console.log('the filter', theFilter, namesToShow)
const addNumber = (event) => {
event.preventDefault()
const numberObject = {
id: bookData.length + 1,
details: {
name: newName,
number: newNumber,
}
}
if(numberObject.details.name !== "" && numberObject.details.number !== '') {
setBookData(bookData.concat(numberObject))
setNewName('')
setNewNumber('')
setErrorMessage('')
} else {
if(numberObject.details.name === "" && numberObject.details.number === "") {
setErrorMessage('You must enter a name and number!!')
} else if(numberObject.details.number === "") {
setErrorMessage('You must enter a number!!')
} else {
setErrorMessage('You must enter a name!!!')
}
}
}
const handleFilterChange = (event) => {
setTheFilter(event.target.value)
console.log(theFilter)
if(theFilter === '') {
setNamesToShow(bookData.map(person => person.details))
console.log('help')
} else {
console.log('bookData', bookData.map(person => person.details))
setNamesToShow(bookData.map(person => person.details).filter(person => person.name.includes(theFilter)))
console.log('filter', theFilter)
console.log('potential namestoshow?', bookData.map(person => person.details).filter(person => person.name.includes(theFilter)))
console.log('namestoshow', namesToShow)
}
}
const handleNameChange = (event) => {
setNewName(event.target.value)
}
const handleNumberChange = (event) => {
setNewNumber(event.target.value)
}
return (
<>
<h1>Phonebook</h1>
<div>
<input value={theFilter} onChange={handleFilterChange} placeholder='Search for a name' />
{namesToShow.map(person => (
<p>{person.name}: {person.number}</p>
))}
</div>
<form>
<input value={newName} onChange={handleNameChange} placeholder='Enter a name...'/>
<input value={newNumber} onChange={handleNumberChange} placeholder='Enter a number...'/>
<button type='submit' onClick={addNumber}>Save</button>
</form>
<div>
{errorMessage}
</div>
</>
)
}
ReactDOM.render(
<App props={phonebook} />,
document.getElementById('root')
)
【问题讨论】:
-
这能回答你的问题吗? Why calling react setState method doesn't mutate the state immediately? 状态更新是异步的,所以在
handleFilterChange中,当你setTheFilter(event.target.value)之后在同一个函数中尝试使用theFilter,theFilter具有来自 current 渲染周期的值,而不是下一个排队了。 -
要么在函数中使用值
event.target.value进行过滤,要么使用useEffect挂钩适当地响应theFilter状态值更新。 -
非常感谢,这是有道理的。我在 handleFilterChange 中切换了 event.target.value 的过滤器并且工作正常。
标签: javascript reactjs search filter