ReactJS - useTransition 钩子



在 React 18 中,新的钩子称为 useTransition 钩子。因此,我们将研究 useTransition 钩子的基础知识,以及如何利用它来提高 React 应用程序的性能。

性能是创建交互式用户界面时要考虑的重要因素。借助 useTransition,钩子是一种提高 React 应用程序性能的技术。通过将连接到动画的状态更改与组件中的其他状态更改分开,此钩子使我们能够在不中断用户界面的情况下更新状态。

我们可以决定哪些状态更改是紧急的或关键的,哪些没有使用 useTransition 钩子。

在 React 中,所有状态更新都被认为是必不可少的。它可以进行一些快速的 UI 更改,例如从下拉菜单中选择一个值。

语法


const [isPending, startTransition] = useTransition()

参数

useTransition 钩子不接受任何参数。

返回值

钩子 useTransition 返回一个包含两个元素的数组。
  • isPending - isPending 标志显示当前正在等待转换。
  • startTransition - 可以使用 startTransition 函数将状态更新定义为过渡。

如何使用?

在 React 中,我们可以使用 useTransition 返回的 startTransition 函数将状态更新定义为过渡。


function Container() {
	 	const [isPending, startTransition] = useTransition();
	 	const [screen, setScreen] = useState('home');
	 	function selectScreen(nextScreen) {
	 	 	 startTransition(() => {
	 	 	 	 	setScreen(nextScreen);
	 	 	 });
	 	}
}

我们可以以不同的方式使用给定的钩子 'useTransition',例如在过渡过程中更改主要部分。因此,我们将借助一个示例来详细讨论这一点。

例子

示例 - 任务列表应用程序

在这个应用程序中,我们将有一个带有两个屏幕的任务列表:一个用于查看任务,另一个用于查看已完成任务的屏幕。此外,我们还将拥有按钮,可让您在这些屏幕之间切换。因此,下面给出了使用此useTransition钩子的应用程序的代码 -


import React, { useState, useTransition } from 'react';

function Container() {
	 	const [isPending, startTransition] = useTransition();
	 	const [screen, setScreen] = useState('tasks'); 		
	 	function selectScreen(nextScreen) {
	 	 	 startTransition(() => {
	 	 	 	 	setScreen(nextScreen);
	 	 	 });
	 	}
	 	
	 	return (
	 	 	 <div>
	 	 	 	 	<h1>My Task List App</h1>
	 	 	 	 	{screen === 'tasks' && (
	 	 	 	 	 	 <div>
	 	 	 	 	 	 	 	<p>Task 1: Complete React App</p>
	 	 	 	 	 	 	 	<p>Task 2: Learn Hooks</p>
	 	 	 	 	 	 </div>
	 	 	 	 	)}
	 	 	 	 	{screen === 'completed' && (
	 	 	 	 	 	 <div>
	 	 	 	 	 	 	 	<p>Completed Tasks:</p>
	 	 	 	 	 	 	 	<p>Task 1: Complete React App</p>
	 	 	 	 	 	 </div>
	 	 	 	 	)}
	 	 	 	 	<button onClick={() => selectScreen('tasks')}>View Tasks</button>
	 	 	 	 	<button onClick={() => selectScreen('completed')}>View Completed</button>
	 	 	 </div>
	 	);
}

export default Container;

输出

我的任务列表应用程序

示例 - 在过渡期间更改主要部分

我们可以使用 useTransition 钩子来更改父组件的状态。例如,当我们单击此 LightSwitch 组件中的选项卡时,它会修改父组件的状态。此更新被视为一种过渡,使我们能够轻松地在选项卡之间导航,而不会出现用户交互延迟。


export default function LightSwitch({ isOn, toggleSwitch }) {
	 	const [isPending, startTransition] = useTransition();
	 	return (
	 	 	 <button onClick={() => {
	 	 	 	 	startTransition(() => {
	 	 	 	 	 	 toggleSwitch(); // This updates the parent's state.
	 	 	 	 	});
	 	 	 }}>
	 	 	 {isOn ? "Turn Off" : "Turn On"}
	 	 	 </button>
	 	);
}

当我们单击该按钮时,LightSwitch 组件将更改父组件中灯开关的状态。这种状态变化被处理为一个过渡,使我们能够毫无延迟地打开和关闭灯。

因此,我们将创建一个小应用程序来展示 useTransition 钩子的用法,以便更好地理解。

应用程序

让我们构建一个小应用程序,使用选项卡在不同部分之间切换。

此应用程序将分为三个选项卡:“主页”、“产品”和“联系人”。当我们单击选项卡时,会显示相关内容。通过使用 useTransition 钩子,我们将提供平滑的选项卡过渡,它将模拟一个基本的网站布局,我们可以在其中访问有关主页、项目和联系信息的信息。

TabButton.js


import { useTransition } from 'react';

export default function TabButton({ children, isActive, onClick }) {
	 	const [isPending, startTransition] = useTransition();
	 	if (isActive) {
	 	 	 return <b>{children}</b>
	 	}
	 	return (
	 	 	 <button onClick={() => {
	 	 	 	 	startTransition(() => {
	 	 	 	 	 	 onClick();
	 	 	 	 	});
	 	 	 }}>
	 	 	 {children}
	 	 	 </button>
	 	);
}

Home.js


export default function Home() {
	 	return (
	 	 	 <div>
	 	 	 	 	<h2>Welcome to our Home page!</h2>
	 	 	 	 	<p>This is the main page of our website.</p>
	 	 	 </div>
	 	);
}

Products.js


export default function Products() {
	 	return (
	 	 	 <div>
	 	 	 	 	<h2>Our Products</h2>
	 	 	 	 	<ul>
	 	 	 	 	 	 <li>Product 1</li>
	 	 	 	 	 	 <li>Product 2</li>
	 	 	 	 	 	 <li>Product 3</li>
	 	 	 	 	</ul>
	 	 	 </div>
	 	);
}

Contact.js


export default function Contact() {
	 	return (
	 	 	 <div>
	 	 	 	 	<h2>Contact Us</h2>
	 	 	 	 	<p>You can reach us via email or phone:</p>
	 	 	 	 	<ul>
	 	 	 	 	 	 <li>Email: contact@mywebsite.com</li>
	 	 	 	 	 	 <li>Phone: 12345 - 67890</li>
	 	 	 	 	</ul>
	 	 	 </div>
	 	);
}

App.js


import { useState } from 'react';
import TabButton from './TabButton';
import Home from './Home';
import Products from './Products';
import Contact from './Contact';

export default function App() {
	 	const [tab, setTab] = useState('home');
	 	return (
	 	 	 <>
	 	 	 	 	<TabButton
	 	 	 	 	 	 isActive={tab === 'home'}
	 	 	 	 	 	 onClick={() => setTab('home')}
	 	 	 	 	>
	 	 	 	 	 	 Home
	 	 	 	 	</TabButton>
	 	 	 	 	<TabButton
	 	 	 	 	 	 isActive={tab === 'products'}
	 	 	 	 	 	 onClick={() => setTab('products')}
	 	 	 	 	>
	 	 	 	 	 	 Products
	 	 	 	 	</TabButton>
	 	 	 	 	<TabButton
	 	 	 	 	 	 isActive={tab === 'contact'}
	 	 	 	 	 	 onClick={() => setTab('contact')}
	 	 	 	 	>
	 	 	 	 	 	 Contact
	 	 	 	 	</TabButton>
	 	 	 	 	<hr />
	 	 	 	 	{tab === 'home' && <Home />}
	 	 	 	 	{tab === 'products' && <Products />}
	 	 	 	 	{tab === 'contact' && <Contact />}
	 	 	 </>
	 	);
}

输出

网站首页

示例 - 计数器容器应用程序(递增/递减)

这是另一个使用 Container 函数和 useTransition 和 useState 的 React 应用的简单示例。这个应用程序是一个基本的计数器应用程序。有一个从 0 开始的计数器。我们可以单击“增加”按钮来增加计数,单击“减少”按钮来减少它。计数显示在屏幕上,过渡用于在更新计数时提供流畅的用户体验。此应用程序的代码如下 -


import React, { useState, useTransition } from 'react';

function Container() {
	 	const [isPending, startTransition] = useTransition();
	 	const [count, setCount] = useState(0);
	 	
	 	function increment() {
	 	 	 startTransition(() => {
	 	 	 	 	setCount(count + 1);
	 	 	 });
	 	}
	 	
	 	function decrement() {
	 	 	 startTransition(() => {
	 	 	 	 	setCount(count - 1);
	 	 	 });
	 	}
	 	
	 	return (
	 	 	 <div>
	 	 	 	 	<h1>Simple Counter App</h1>
	 	 	 	 	<p>Count: {count}</p>
	 	 	 	 	<button onClick={increment}>Increment</button>
	 	 	 	 	<button onClick={decrement}>Decrement</button>
	 	 	 </div>
	 	);
}

export default Container;

输出

简单的计数器应用程序

局限性

  • UseTransition 只能在代码的特定部分中使用,例如组件或自定义方法。我们应该使用“startTransition”来从其他地方开始过渡,而不是“startTransition”。
  • 只有当我们有权访问修改状态的函数时,我们才能将其置于过渡状态。如果我们想开始转换以响应变量或自定义函数之类的东西,我们应该使用“useDeferredValue”。
  • 我们赋予“startTransition”的函数必须快速且简单明了。React 将立即运行它,在此期间发生的任何状态更改都将被视为过渡。如果我们稍后尝试进行更多状态更改,例如使用超时,它们将不会被视为过渡。
  • 转换可能会被其他状态更改中断。例如,如果我们在过渡期间更新图表,然后开始输入输入字段,React 将停止图表更新并首先处理输入。
  • 过渡不能用于控制文本输入字段。
  • 如果同时发生多个转换,React 会将它们组合在一起。