问题:
I have a component that displays search data returned from the Spotify API. However, every time I update the state the UI flickers:
Input:
<DebounceInpu...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
I have a component that displays search data returned from the Spotify API. However, every time I update the state the UI flickers:
Input:
<DebounceInput
debounceTimeout={300}
onChange={handleChange}
/>
Hook:
const [searchResults, setSearchResults] = useState(null)
API call w/ Apollo:
const searchSpotify = async (query) => {
const result = await props.client.query({
query: SearchTracks,
variables: {
query
}
})
const tracks = result.data.searchedTracks
setSearchResults(tracks)
}
Render:
{searchResults &&
<div className="search-results">
{searchResults.map((song) => (
<SongInfo key={song.id} {...song} />
))}
</div>
}
I noticed it only happens on the first load. For example, if I were to type the query again it shows without flickering. Is there a better way to implement this so the UI doesn't flicker?
回答1:
Below are the frames that cause the flicker. What I think is happening is it takes some time for the images to load. While they are loading the items have reduced height. You should make sure SongInfo
layout does not depend on whether the image has been loaded or not.
Images not loaded - items are collapsed:
Images were loaded:
回答2:
I think whats happening is that you are executing a search query on every key stroke which is causing the weird behavior.
Use lodash debounce to avoid doing a search on every key stroke. That should address the flickering. (Also, adding a loading state will help)
Sample debounce component
import React, {Component} from 'react'
import { debounce } from 'lodash'
class TableSearch extends Component {
//********************************************/
constructor(props){
super(props)
this.state = {
value: props.value
}
this.changeSearch = debounce(this.props.changeSearch, 250)
}
//********************************************/
handleChange = (e) => {
const val = e.target.value
this.setState({ value: val }, () => {
this.changeSearch(val)
})
}
//********************************************/
render() {
return (
<input
onChange = {this.handleChange}
value = {this.props.value}
/>
)
}
//********************************************/
}