一文带你了解React中的并发机制

 更新时间:2024年03月29日 16:43:44   作者:纯爱掌门人  
React 18.2.0 引入了一系列并发机制的新特性,旨在帮助各位开发者更好地控制和优化应用程序的性能和用户体验,下面我们就来看看如何利用这些新特性构建更高效、更响应式的应用程序吧

一、自动批处理

React 现在可以自动将多个状态更新操作批量处理,以减少不必要的渲染和提高性能。这意味着,当你在一个事件处理程序中连续调用多个状态更新函数时,React 会将它们合并为一次更新,从而减少渲染次数。

计数器

在下面这个案例中,当用户点击按钮时,handleClick 函数会连续调用三次 setCount。由于 React 的自动批处理,这三次更新会被合并为一次更新,从而减少渲染次数。

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
    setCount(count + 2);
    setCount(count + 3);
  };

  return (
    <div>
      <p>Count: {count}</p>
     <button onClick={handleClick}>Increment by 3</button>
    </div>
  );
}

二、异步渲染

React现在可以支持异步渲染,这意味着 React 可以在渲染过程中暂停和恢复,从而允许其他任务(如用户输入或动画)优先执行。这有助于提高应用程序的响应性和性能。

异步数据获取

在下面这个案例中,AsyncComponent 组件在挂载时会异步获取数据。由于 React 的异步渲染,当数据还未获取到时,组件会显示 "Loading...",而不会阻塞其他任务的执行。

import { useState, useEffect } from 'react';

function AsyncComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchData().then((fetchedData) => {
      setData(fetchedData);
    });
  }, []);

  if (data === null) {
    return <p>Loading...</p>;
  }

  return <div>{data}</div>;
}

async function fetchData() {
  // 模拟异步数据获取
  await new Promise((resolve) => setTimeout(resolve, 1000));
  return 'Async data';
}

三、useDeferredValue:延迟值更新

useDeferredValue 是一个新的 Hook,它允许你在渲染过程中延迟某些值的更新,直到下一次渲染。这对于实现响应式 UI 和避免不必要的渲染非常有用。

输入框防抖

在下面这个示例中,当用户在输入框中输入文本时,useDeferredValue 会延迟更新 deferredText,直到 500 毫秒后的下一次渲染。这有助于提高应用程序的响应性和性能。

import { useState, useDeferredValue } from 'react';

function DebounceInput() {
  const [text, setText] = useState('');
  const deferredText = useDeferredValue(text, { timeoutMs: 500 });

  const handleChange = (e) => {
    setText(e.target.value);
  };

  return (
    <div>
     <input type="text" value={text} onChange={handleChange} />
      <p>Debounced value: {deferredText}</p>
    </div>
  );
}

四、useTransition:创建过渡状态

useTransition 是一个新的 Hook,它允许你在状态更新过程中创建一个过渡(transition),从而实现更细粒度的更新控制。你可以使用这个 Hook 来延迟某些状态更新,直到过渡完成。这对于实现更好的用户体验和性能优化非常有用。

加载状态与过渡效果

在下面这个示例中,当用户点击按钮时,handleClick 函数会使用 startTransition 创建一个过渡,并在过渡期间延迟更新 countisPending 变量表示过渡是否正在进行中,当过渡正在进行时,会显示 "Loading..."。

import { useState, useTransition } from 'react';

function TransitionExample() {
  const [count, setCount] = useState(0);
  const [isPending, startTransition] = useTransition();

  const handleClick = () => {
    startTransition(() => {
      setCount(count + 1);
    });
  };

  return (
    <div>
      <p>Count: {count}</p>
     <button onClick={handleClick}>Increment</button>
      {isPending && <p>Loading...</p>}
    </div>
  );
}

五、Suspense 配置优化

React新版本引入了新的 Suspense 配置选项,如 timeoutMs 和 fallbackAfterSuspense。这些选项允许你更精细地控制 Suspense 的行为,例如设置挂起时间和在挂起后显示备用内容。

分页加载与错误处理

在下面这个示例中,App 组件使用 Suspense 包裹了两个异步加载的页面组件 Page1 和 Page2。通过设置 timeoutMs 为 1000 毫秒,我们可以在 1 秒后显示 fallbackAfterSuspense 属性指定的备用内容 "Loading with suspense..."。同时,当 Page2 加载失败时,Suspense 会捕获错误并显示默认的错误边界内容

import { Suspense } from 'react';

function App() {
  return (
    <Suspense
      fallback={<div>Loading...</div>}
      timeoutMs={1000}
      fallbackAfterSuspense={<div>Loading with suspense...</div>}
    >
      <Page1 />
      <Page2 />
    </Suspense>
  );
}

function Page1() {
  // 模拟异步数据获取
  return new Promise((resolve) => setTimeout(() => resolve(<div>Page 1</div>), 2000));
}

function Page2() {
  // 模拟异步数据获取失败
  return new Promise((_, reject) => setTimeout(() => reject(new Error('Error loading Page 2')), 2000));
}

六、startTransition:手动创建过渡

startTransition 是一个新的函数,它允许你在状态更新过程中创建一个过渡(transition)。你可以使用这个函数来延迟某些状态更新,直到过渡完成。这对于实现更好的用户体验和性能优化非常有用。

动画与过渡的协同

在下面这个示例中,当用户点击按钮时,handleClick 函数会使用 startTransition 创建一个过渡,并在过渡期间平滑地移动盒子。通过结合 CSS 动画和 React 过渡,可以实现更自然、更流畅的交互体验。

import { useState, startTransition } from 'react';

function AnimationTransitionExample() {
  const [position, setPosition] = useState(0);

  const handleClick = () => {
    // 使用 startTransition 创建过渡
    startTransition(() => {
      setPosition(position + 100);
    });
  };

  return (
    <div style={{ position: 'relative' }}>
      <div
        style={{
          position: 'absolute',
          left: position,
          transition: 'left 0.5s ease-out',
        }}
      >
        Box
      </div>
     <button onClick={handleClick}>Move box</button>
    </div>
  );
}

七、useId 与 useSyncExternalStore:与外部数据源同步

这两个新的 Hooks 提供了更好的支持,以便在 React 组件和外部数据源之间同步数据。useId 用于生成唯一的 ID,而 useSyncExternalStore 用于在组件和外部数据源之间同步数据。

实时聊天应用

在下面这个示例中,ChatRoom 组件使用 useSyncExternalStore 从外部数据源(chatStore)获取聊天消息列表。当外部数据源的数据发生变化时,组件会自动重新渲染。同时,每个 ChatMessage 组件都使用 useId 生成了一个唯一的 ID,以便在 DOM 中正确引用它们。

import { useId, useSyncExternalStore } from 'react';

function ChatMessage({ message }) {
  const id = useId();
  return <div id={`message-${id}`}>{message}</div>;
}

function ChatRoom() {
  const messages = useSyncExternalStore(
    () => chatStore.subscribe,
    () => chatStore.getMessages()
  );

  return (
    <div>
      {messages.map((message) => (
        <ChatMessage key={message.id} message={message.text} />
      ))}
    </div>
  );
}

const chatStore = {
  messages: [],
  subscribers: new Set(),

  subscribe(callback) {
    this.subscribers.add(callback);
    return () => {
      this.subscribers.delete(callback);
    };
  },

  getMessages() {
    return this.messages;
  },

  addMessage(message) {
    this.messages.push(message);
    this.subscribers.forEach((callback) => callback());
  },
};

总结以及预测

React新版本的并发机制提供了一系列新特性,包括自动批处理、异步渲染、新的 Hooks 和 Suspense 配置等。这些特性旨在帮助开发者更好地控制和优化应用程序的性能和用户体验。通过这些新特性我看到了React在性能优化和用户体验方面的巨大潜力。

下面是掌门人对于React并发机制的一些预测,若是大家与我想法不一致,还请嘴下留情。

  • 更细粒度的并发控制:未来的React可能会提供更细粒度的并发控制,允许开发者根据具体场景定制渲染策略,以实现更高的性能和更低的开销。
  • 集成Web Workers:Web Workers为JavaScript提供了在单独线程中运行代码的能力,从而避免了主线程的阻塞。未来,React可能会更好地集成Web Workers,以实现更高效的并发处理。
  • 更强大的Suspense功能:Suspense是React并发机制的核心组件之一,未来的版本可能会增强其功能,例如支持多个等待状态、更细粒度的错误处理等。
  • 优化的数据流管理:React的上下文API和数据流管理一直是开发者关注的焦点。未来的React可能会进一步优化这些方面,以提供更高效、更简洁的数据流解决方案。
  • 更好的服务器端渲染支持:随着服务器端渲染(SSR)在现代Web应用中的重要性日益增加,React可能会提供更好的SSR支持,包括更快的首屏加载时间、更好的SEO优化等。

从长远来看,React的发展将更加注重性能、可维护性和开发者体验,React目前的发展趋势应该是将自身打造为一个全栈底层的基座,同时,随着物联网设备的普及,React也可能会拓展其在该领域的应用。

到此这篇关于一文带你了解React中的并发机制的文章就介绍到这了,更多相关React并发机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • React hooks useState异步问题及解决

    React hooks useState异步问题及解决

    这篇文章主要介绍了React hooks useState异步问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 解决React报错Property 'value' does not exist on type EventTarget

    解决React报错Property 'value' does not exist on 

    这篇文章主要为大家介绍了React报错Property 'value' does not exist on type EventTarget的解决方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • React组件学习之Hooks使用

    React组件学习之Hooks使用

    这篇文章主要介绍了React hooks组件通信,在开发中组件通信是React中的一个重要的知识点,本文通过实例代码给大家讲解react hooks中常用的父子、跨组件通信的方法,需要的朋友可以参考下
    2022-08-08
  • React Navigation 路由传参的操作代码

    React Navigation 路由传参的操作代码

    这篇文章主要介绍了React Navigation 路由传参,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • webpack手动配置React开发环境的步骤

    webpack手动配置React开发环境的步骤

    本篇文章主要介绍了webpack手动配置React开发环境的步骤,webpack手动配置一个独立的React开发环境, 开发环境完成后, 支持自动构建, 自动刷新, sass语法 等功能...感兴趣的小伙伴们可以参考一下
    2018-07-07
  • React 条件判断实例详解

    React 条件判断实例详解

    在 React 中,可以通过 JavaScript 的条件语句来动态渲染组件或元素,下面给大家分享几种常用的在 React 中处理条件渲染的方法,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • React应用框架Dva数据流向原理总结分析

    React应用框架Dva数据流向原理总结分析

    这篇文章主要为大家介绍了React 应用框架Dva数据流向原理总结分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • React Native预设占位placeholder的使用

    React Native预设占位placeholder的使用

    本篇文章主要介绍了React Native预设占位placeholder的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • react配置代理setupProxy.js无法访问v3.0版本问题

    react配置代理setupProxy.js无法访问v3.0版本问题

    这篇文章主要介绍了react配置代理setupProxy.js无法访问v3.0版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • react自定义实现状态管理详解

    react自定义实现状态管理详解

    这篇文章主要为大家详细介绍了react如何自定义实现状态管理,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01

最新评论