React 18 是 Facebook 推出的 JavaScript 库 React 的最新版本,带来了许多新功能和改进。
React 18 的主要特性
1.1 并发模式 (Concurrent Mode)
并发模式是 React 18 的核心功能之一,旨在提升应用的响应速度和用户体验。并发模式允许 React 在后台准备多个 UI 更新,而不会阻塞主线程。这样,当主线程空闲时,可以迅速切换到这些预准备的更新上,从而减少用户界面的卡顿现象。
并发模式的主要特性包括:
- 自动批处理 (Automatic Batching):在 React 18 中,多个状态更新可以自动批处理,从而减少不必要的渲染次数,提高性能。
- 可中断渲染 (Interruptible Rendering):React 可以在渲染过程中暂停当前任务,处理更高优先级的任务,然后继续之前的任务。这使得 UI 更加流畅和响应快速。
- 优先级调度 (Priority Scheduling):React 18 引入了优先级调度机制,根据任务的重要性和紧急程度,合理分配资源,从而优化用户体验。
1.2 自动批处理 (Automatic Batching)
在 React 18 之前,状态更新通常会触发多次渲染。而在 React 18 中,自动批处理功能可以将多个状态更新合并为一个渲染,从而减少渲染次数,提高性能。
代码语言:txt复制// 之前版本
function handleClick() {
setCount(count 1);
setFlag(true);
// 这将导致两次重新渲染
}
// React 18
function handleClick() {
setCount(count 1);
setFlag(true);
// 这只会导致一次重新渲染
}
1.3 并发渲染 API
React 18 引入了一些新的 API 来支持并发渲染:
startTransition
:标记非紧急更新,使其在资源允许时进行渲染。useTransition
:用于管理并发状态更新,提供挂起状态和过渡状态。useDeferredValue
:推迟计算代价高昂的值,提升应用性能。
import { useTransition } from 'react';
function App() {
let [isPending, startTransition] = useTransition();
function handleClick() {
startTransition(() => {
setCount(count 1);
});
}
return (
<div>
{isPending ? "Loading..." : count}
<button onClick={handleClick}>Increment</button>
</div>
);
}
1.4 新的 SSR 改进
React 18 对服务器端渲染 (SSR) 也进行了显著改进,提升了性能和用户体验:
- 流式渲染 (Streaming Rendering):允许服务器逐步向客户端发送 HTML,从而提高首屏渲染速度。
- 服务器组件 (Server Components):服务器组件是可以在服务器端渲染的 React 组件,能够减少客户端的 JavaScript 负载。
下面是一个简单的步骤说明和代码示例, React 18 和 TypeScript 创建一个基本的旅游电商平台。
React 18 TypeScript 打造旅游电商平台
项目初始化
- 创建新项目:
npx create-react-app travel-ecommerce --template typescript
cd travel-ecommerce
- 安装必要的依赖:
npm install react-router-dom @types/react-router-dom
项目结构
创建如下项目结构:
代码语言:txt复制src/
|-- components/
| |-- ProductCard.tsx
|-- pages/
| |-- HomePage.tsx
| |-- ProductListPage.tsx
| |-- ProductDetailPage.tsx
|-- App.tsx
|-- index.tsx
|-- types/
| |-- index.ts
定义类型
在 src/types/index.ts
文件中定义产品类型:
export interface Product {
id: number;
name: string;
description: string;
price: number;
imageUrl: string;
}
创建组件
ProductCard 组件 (src/components/ProductCard.tsx
):
import React from 'react';
import { Product } from '../types';
interface ProductCardProps {
product: Product;
}
const ProductCard: React.FC<ProductCardProps> = ({ product }) => {
return (
<div className="product-card">
<img src={product.imageUrl} alt={product.name} />
<h3>{product.name}</h3>
<p>{product.description}</p>
<p>${product.price}</p>
</div>
);
};
export default ProductCard;
HomePage 组件 (src/pages/HomePage.tsx
):
import React from 'react';
import { Link } from 'react-router-dom';
const HomePage: React.FC = () => {
return (
<div>
<h1>Welcome to Travel Ecommerce</h1>
<Link to="/products">View Products</Link>
</div>
);
};
export default HomePage;
ProductListPage 组件 (src/pages/ProductListPage.tsx
):
import React from 'react';
import ProductCard from '../components/ProductCard';
import { Product } from '../types';
const products: Product[] = [
{ id: 1, name: 'Tour Package 1', description: 'Amazing tour package', price: 499, imageUrl: 'https://via.placeholder.com/150' },
// 添加更多产品
];
const ProductListPage: React.FC = () => {
return (
<div>
<h2>Products</h2>
<div className="product-list">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
</div>
);
};
export default ProductListPage;
ProductDetailPage 组件 (src/pages/ProductDetailPage.tsx
):
import React from 'react';
import { useParams } from 'react-router-dom';
import { Product } from '../types';
const products: Product[] = [
{ id: 1, name: 'Tour Package 1', description: 'Amazing tour package', price: 499, imageUrl: 'https://via.placeholder.com/150' },
// 添加更多产品
];
const ProductDetailPage: React.FC = () => {
const { id } = useParams<{ id: string }>();
const product = products.find(p => p.id === Number(id));
if (!product) {
return <div>Product not found</div>;
}
return (
<div>
<h2>{product.name}</h2>
<img src={product.imageUrl} alt={product.name} />
<p>{product.description}</p>
<p>${product.price}</p>
</div>
);
};
export default ProductDetailPage;
设置路由
在 src/App.tsx
文件中设置路由:
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import HomePage from './pages/HomePage';
import ProductListPage from './pages/ProductListPage';
import ProductDetailPage from './pages/ProductDetailPage';
const App: React.FC = () => {
return (
<Router>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/products" element={<ProductListPage />} />
<Route path="/products/:id" element={<ProductDetailPage />} />
</Routes>
</Router>
);
};
export default App;
启动项目
运行以下命令启动项目:
代码语言:txt复制npm start