【问题标题】:React: UI Flickering When State UpdatedReact:状态更新时 UI 闪烁
【发布时间】:2019-07-28 15:38:21
【问题描述】:

我有一个显示从 Spotify API 返回的搜索数据的组件。但是,每次我更新状态时,UI 都会闪烁:

输入:

            <DebounceInput
                debounceTimeout={300}
                onChange={handleChange}
            />

钩子:

const [searchResults, setSearchResults] = useState(null)

使用 Apollo 调用 API:

 const searchSpotify = async (query) => {
    const result = await props.client.query({
        query: SearchTracks,
        variables: {
            query
        }
    })
    const tracks = result.data.searchedTracks
    setSearchResults(tracks)
}

渲染:

        {searchResults &&
            <div className="search-results">
                    {searchResults.map((song) => (
                            <SongInfo key={song.id} {...song} />
                    ))}
            </div>
        }

我注意到它只发生在第一次加载时。例如,如果我再次键入查询,它会显示而不会闪烁。有没有更好的方法来实现这一点,这样 UI 就不会闪烁?

【问题讨论】:

  • 你可以添加一个加载状态,当你调用 api 来获取时,你可以切换一个加载标志/状态。
  • 您是否尝试将key 属性添加到您的SongInfo 元素中?类似&lt;SongInfo key={song.id} {...song} /&gt;(将 id 更改为唯一标识您的歌曲的任何属性)。向列表项添加 key prop 可以提高 React 性能。
  • @varoons 加载状态发生得如此之快,以至于它实际上使 UI 变得更糟
  • @abadalyan 我的实际代码中有一个密钥,我尝试为这个问题简化它。我编辑了 组件以澄清
  • 如果将 SongInfo 替换为简单的
    {song.name}
    会闪烁吗?

标签: javascript reactjs react-apollo apollo-client react-hooks


【解决方案1】:

我认为发生的事情是您在每次击键时都执行搜索查询,这会导致奇怪的行为。

使用 lodash debounce 来避免对每个按键进行搜索。 那应该解决闪烁问题。 (另外,添加加载状态会有所帮助)

去抖组件示例

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

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

}

【讨论】:

  • 我实际上使用的是DebounceInput。它确实有帮助,但仍然不理想。我编辑了问题以澄清。
【解决方案2】:

以下是导致闪烁的帧。我认为正在发生的是图像加载需要一些时间。在他们装载物品时,它们的高度降低了。您应该确保SongInfo 布局不依赖于图像是否已加载。

图片未加载 - 项目已折叠:

图片已加载:

【讨论】:

  • 你说得对,这绝对是 的 部分的问题。我设置了默认的高度和宽度,这似乎有帮助,但图像本身在加载/渲染时似乎在闪烁。我现在正在调查。
猜你喜欢
  • 2019-11-28
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
  • 2015-03-18
  • 1970-01-01
  • 2020-07-23
相关资源
最近更新 更多