React: UI Flickering When State Updated

14,312

Solution 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:

enter image description here

Images were loaded:

enter image description here

Solution 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}
        />
    )
  }

  //********************************************/

}
Share:
14,312

Related videos on Youtube

Travis S.
Author by

Travis S.

Updated on June 04, 2022

Comments

  • Travis S.
    Travis S. almost 2 years

    I have a component that displays search data returned from the Spotify API. However, every time I update the state the UI flickers:

    enter image description here 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?

  • Travis S.
    Travis S. about 5 years
    I'm actually using a DebounceInput. It did help but it still isn't ideal. I edited the question to clarify.
  • Travis S.
    Travis S. about 5 years
    You're right, it's definitely an issue with the <img src={song.imageUrl}> part of <SongInfo>. I set a default height and width and that seems to help but the image itself seems to be flickering as it's loading/rendering. I'm looking into it now.