React 最新特性Concurrent(并发)模式 理解(一)

最近,React官方放出了最新特性Concurrent模式(实验阶段)的文档。又是一个非常实用的特性。

什么是并发?官方解释是:并发模式是一些可以帮助React保持响应地和友好地去适应用户设备性能和网速。
也就是React可以根据用户设备的性能和网速做出一些调整,以保证页面能够更流畅的渲染。

React给出了两种并发的应用:数据获取和UI渲染

传统的UI渲染是阻塞式的,在当前任务没有执行完毕时不会去进行下一步的操作,即使有更加紧急的任务也必须等到前面的任务执行完毕。React对此做出了优化,使得UI渲染是可以打断的,在执行Ui渲染时,如果有更加紧急的任务,将会先去执行该任务,等待该任务执行完毕后再去继续执行前面的任务。React官方给出了一个例子:过滤列表的例子。我们在输入框输入内容时,列表就会立刻进行渲染,但渲染是阻塞的,渲染时将不能进行输入,页面会出现卡顿,传统情况下,为了减少渲染次数,我们会用节流和防抖方式进行优化,但是这样还是有些不友好的体验。React引入并发模式后,所有的操作都是可以打断的,我们继续输入的时候,渲染就会被打断,在你输入的空隙就会继续渲染,这样就使得页面的渲染更加流畅。当然这只是非常基本的一种情况,实际上,React还可以做的更多。

React官方把并发模式比作了git的分支操作,React会在主分支上进行操作时,其他的操作可以在其他分支上(后台)完成,等主分支上的任务执行完毕后,就会拿到其它分支上的执行结果进行处理。

在React16.6引入了Suspense,可以优雅的进行异步组件的加载处理。但是现在,Suspense可做的更多。
例如数据的获取:

const resource = fetchProfileData();

function ProfilePage() {
  return (
    <Suspense fallback={<h1>Loading profile...</h1>}>
      <ProfileDetails />
      <Suspense fallback={<h1>Loading posts...</h1>}>
        <ProfileTimeline />
      </Suspense>
    </Suspense>
  );
}

function ProfileDetails() {
  // 尝试去读取用户信息,即使数据还没有获取到
  const user = resource.user.read();
  return <h1>{user.name}</h1>;
}

function ProfileTimeline() {
  // 尝试去帖子列表,即使数据还没有获取到
  const posts = resource.posts.read();
  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.text}</li>
      ))}
    </ul>
  );
}

这也就是并发模式的数据加载方式;在数据还没有加载到的时候,会通过Susepnse显示一个降级的渲染。注意:这里的加载方式必须使用被封装好的并发式的请求工具函数。React官方给我们介绍了两种:Rely、和一个简单的fake api,具体使用可以去React官网查找。通过这种方式就可以在数据加载的时候优雅地提供一个过渡状态。

另一个是UI渲染的并发模式,我们可以在例如按钮点击时不去立刻进行操作(比如进入一个空白页面),而是给他一个延时,在延时结束有才会进行操作(比如页面的跳转),在此期间,我们可以去加载数据,之后的跳转会是一个平滑的过渡,以此可以提升用户体验。

关键API:useTransition,他会返回一个startTransition函数和isPending状态。举个栗子:

function App() {
// 获取数据
  const [resource, setResource] = useState(initialResource);
 // 使用一个Transition,延时三秒
  const [startTransition, isPending] = useTransition({
    timeoutMs: 3000
  });
  return (
    <>
      <button
        disabled={isPending}
        onClick={() => {
          // 点击之后会在三秒后才进行startTransition里的操作
          startTransition(() => {
            const nextUserId = getNextId(resource.userId);
            setResource(fetchProfileData(nextUserId));
          });
        }}
      >
        Next
      </button>
      {isPending ? " Loading..." : null}
      <ProfilePage resource={resource} />
    </>
  );
}

具体参考:React官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容