javascript 在 React.js 中加载异步数据时防止 UI 闪烁
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31016130/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Preventing UI flicker when loading async data in React.js
提问by dumbmatter
I have some data in IndexedDB, which can only be accessed asynchronously. I want to build a React.js UI using that data. The general idea is that I'll have multiple React components that load data from IndexedDB and display some UI based on that data, and the user will be able to switch between which component is currently displayed.
我在IndexedDB中有一些数据,只能异步访问。我想使用该数据构建一个 React.js UI。总体思路是,我将拥有多个 React 组件,它们从 IndexedDB 加载数据并根据该数据显示一些 UI,并且用户将能够在当前显示的组件之间切换。
My concern is that I don't know how to elegantly accomplish this without some superfluous UI flickering. I can do my asynchronous data loading in componentDidMount
and put the data in this.state
, but then render
will be called before it's finished, forcing me to either display nothing or display some placeholder data for a tiny fraction of a second while the data from IndexedDB is retrieved.
我担心的是,如果没有一些多余的 UI 闪烁,我不知道如何优雅地完成此操作。我可以加载异步数据componentDidMount
并将数据放入 中this.state
,但是render
在它完成之前将被调用,这迫使我在检索 IndexedDB 中的数据时不显示任何内容或显示一些占位符数据的一小部分时间。
I'd rather have it not render
until after my data from IndexedDB is loaded. I know it won't take long to load, and I'd rather the previous component continue to display while the new data loads, so there is just one flicker (old -> new) rather than two (old -> blank/placeholder -> new). This is more like how a normal web page works. When you click a link from one website to another, your browser doesn't instantly show a blank/placeholder screen while it waits for the server from the linked website to respond.
我宁愿render
在加载来自 IndexedDB 的数据之后才使用它。我知道加载不会花很长时间,我宁愿在加载新数据时继续显示前一个组件,所以只有一个闪烁(旧 -> 新)而不是两个(旧 -> 空白/占位符) -> 新)。这更像是普通网页的工作方式。当您单击从一个网站到另一个网站的链接时,您的浏览器在等待链接网站的服务器响应时不会立即显示空白/占位符屏幕。
I'm thinking I could do my data loading outside of the React component before calling React.render
and then passing it in via this.props
. But that seems messy, because nesting components would become tricky and some of my components will be updating over time and pulling new data from IndexedDB, through the exact same code that initializes them. So it seems like an ideal use case for storing data in this.state
because then I could update it within the component itself when I get a signal that new data is available. Initialization and updating would be as easy as calling a this.loadData()
function that sets some values in this.state
... but then I have the aforementioned extra flicker.
我想我可以在调用之前在 React 组件之外加载数据React.render
,然后通过this.props
. 但这似乎很混乱,因为嵌套组件会变得棘手,而且我的一些组件将随着时间的推移而更新,并通过初始化它们的完全相同的代码从 IndexedDB 中提取新数据。所以这似乎是存储数据的理想用例,this.state
因为当我收到新数据可用的信号时,我可以在组件本身内更新它。初始化和更新就像调用一个this.loadData()
在this.state
...中设置一些值的函数一样简单,但是我有前面提到的额外闪烁。
Does anyone have any better ideas? What's the canonical solution to this problem? Is it really to just have millisecond blank/placeholder flickers all over the place?
有没有人有更好的想法?这个问题的规范解决方案是什么?真的只是在整个地方都有毫秒的空白/占位符闪烁吗?
采纳答案by Joe P
From the comments it sounds like the behavior you have in the previous implementation (waiting to navigate until you have fetched the necessary data) is the desired goal. If that's the case, the best way to do this without having the flickering would be to use some external object to manage the state and pass the data as props when it has been fetched.
从评论来看,您在之前的实现中的行为(等待导航,直到您获取必要的数据)是您想要的目标。如果是这种情况,在没有闪烁的情况下执行此操作的最佳方法是使用一些外部对象来管理状态并在获取数据时将数据作为道具传递。
React Router has a pretty good solution where it has the willTransitionTo hook to fetch data for a given component before navigating. This has the added benefit of allowing you to easily catch errors if something goes wrong.
React Router 有一个很好的解决方案,它有 willTransitionTo 钩子在导航之前获取给定组件的数据。这还有一个额外的好处,即如果出现问题,您可以轻松捕获错误。
Updated with new link:
更新了新链接: