自动批处理

使用set函数时不会像之前执行一个set函数渲染一次界面(更改一个状态渲染一次界面),会等到某一处理函数中set函数都执行完了之后渲染界面(只在最后渲染界面)
example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const handleClick = () =>{
setIsFetching(false);
setStatus('success');
}

// Before: only React events were batched.
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will render twice, once for each state update (no batching)
}, 1000);

// After: updates inside of timeouts, promises,
// native event handlers or any other event are batched.
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}, 1000);

新的客户端和服务器渲染 API

  • createRoot
1
2
3
4
5
6
7
8
9
10
// Before
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);

// After
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(<App tab="home" />);
  • hydrateRoot

新功能 transition

react.memo

支持 Suspense 的流式服务器端渲染

某一组件先加载出来,某一组件后加载出来(服务端返回的html),就可以使用Suspense,提升用户体验
In React 18, we’ve added support for Suspense on the server and expanded its capabilities using concurrent rendering features.

Suspense in React 18 works best when combined with the transition API. If you suspend during a transition, React will prevent already-visible content from being replaced by a fallback. Instead, React will delay the render until enough data has loaded to prevent a bad loading state.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 该组件是动态加载的
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
return (
// 显示 <Spinner> 组件直至 OtherComponent 加载完成
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}

新的严格模式行为

新的钩子

  • useId
    useId用于在客户端和服务器上生成唯一 ID,同时避免水合不匹配。它主要用于与需要唯一 ID 的可访问性 API 集成的组件库。这解决了 React 17 及更低版本中已经存在的问题,但在 React 18 中更为重要,因为新的流式服务器渲染器如何无序交付 HTML。

  • useTransition

  • startTransition
    useTransition并startTransition让您将一些状态更新标记为不紧急。默认情况下,其他状态更新被认为是紧急的。React 将允许紧急状态更新(例如,更新文本输入)以中断非紧急状态更新(例如,呈现搜索结果列表)。

  • useDeferredValue
    useDeferredValue让您推迟重新渲染树的非紧急部分。它类似于去抖动,但与之相比有一些优点。没有固定的时间延迟,因此 React 将在第一次渲染反映在屏幕上后立即尝试延迟渲染。延迟渲染是可中断的,不会阻止用户输入。

  • useSyncExternalStore
    useSyncExternalStore是一个新的钩子,它允许外部存储通过强制对存储的更新同步来支持并发读取。在实现对外部数据源的订阅时,它消除了对 useEffect 的需要,并且推荐用于任何与 React 外部状态集成的库。

  • useInsertionEffect
    useInsertionEffect它允许 CSS-in-JS 库解决在渲染中注入样式的性能问题。除非您已经构建了 CSS-in-JS 库,否则我们不希望您使用它。这个钩子将在 DOM 发生变异之后运行,但在布局效果读取新布局之前。这解决了在 React 17 及更低版本中已经存在的问题,但在 React 18 中更为重要,因为 React 在并发渲染期间屈服于浏览器,使其有机会重新计算布局。

详细更新日志