React 完全教程
React 是由 Facebook 开发的用于构建用户界面的 JavaScript 库。它采用组件化的开发方式,让构建复杂的 UI 变得简单高效。
为什么选择 React?
- 组件化:将 UI 拆分成独立、可复用的组件
- 声明式:描述 UI 应该是什么样子,React 负责更新
- 虚拟 DOM:高效的 DOM 更新机制
- 生态丰富:庞大的社区和丰富的第三方库
- 跨平台:React Native 支持移动端开发
环境搭建
使用 Vite 创建项目
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
npm install
npm run dev使用 Next.js(推荐)
npx create-next-app@latest my-app
cd my-app
npm run dev核心概念
1. JSX
JSX 是 JavaScript 的语法扩展,让你可以在 JavaScript 中编写类似 HTML 的代码。
function Welcome() {
const name = "World";
return (
<div>
<h1>Hello, {name}!</h1>
<p>Welcome to React</p>
</div>
);
}JSX 规则:
- 必须返回单个根元素(或使用 Fragment
<>...</>) - 所有标签必须闭合
- 使用
className代替class - 使用
{}嵌入 JavaScript 表达式
2. 组件
组件是 React 的核心概念,有两种定义方式:
函数组件(推荐):
function Button({ text, onClick }) {
return (
<button onClick={onClick}>
{text}
</button>
);
}类组件(传统方式):
class Button extends React.Component {
render() {
return (
<button onClick={this.props.onClick}>
{this.props.text}
</button>
);
}
}3. Props
Props 是组件的输入,用于父组件向子组件传递数据。
function UserCard({ name, email, avatar }) {
return (
<div className="user-card">
<img src={avatar} alt={name} />
<h3>{name}</h3>
<p>{email}</p>
</div>
);
}
// 使用组件
<UserCard
name="张三"
email="zhangsan@example.com"
avatar="/avatar.jpg"
/>Props 的特点:
- 只读,不能修改
- 可以传递任何类型的数据
- 可以设置默认值
function Button({ text = "点击", variant = "primary" }) {
return <button className={variant}>{text}</button>;
}4. State
State 是组件的内部状态,当 state 改变时,组件会重新渲染。
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
增加
</button>
<button onClick={() => setCount(count - 1)}>
减少
</button>
</div>
);
}React Hooks
Hooks 是 React 16.8 引入的新特性,让函数组件也能使用 state 和其他 React 特性。
useState
管理组件状态。
const [state, setState] = useState(initialValue);示例:
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log({ name, email });
};
return (
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="姓名"
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="邮箱"
/>
<button type="submit">提交</button>
</form>
);
}useEffect
处理副作用(数据获取、订阅、DOM 操作等)。
useEffect(() => {
// 副作用代码
return () => {
// 清理函数(可选)
};
}, [dependencies]);示例:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUser() {
setLoading(true);
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUser(data);
setLoading(false);
}
fetchUser();
}, [userId]); // 当 userId 改变时重新执行
if (loading) return <div>加载中...</div>;
if (!user) return <div>用户不存在</div>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}useContext
跨组件共享数据,避免 props 层层传递。
import { createContext, useContext, useState } from 'react';
// 创建 Context
const ThemeContext = createContext();
// Provider 组件
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
// 使用 Context
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button
className={theme}
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
>
切换主题
</button>
);
}useRef
访问 DOM 元素或保存可变值。
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>聚焦输入框</button>
</div>
);
}useMemo 和 useCallback
性能优化 Hooks。
// useMemo:缓存计算结果
const expensiveValue = useMemo(() => {
return computeExpensiveValue(a, b);
}, [a, b]);
// useCallback:缓存函数
const handleClick = useCallback(() => {
console.log('clicked');
}, []);自定义 Hook
封装可复用的逻辑。
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}
// 使用
function App() {
const [name, setName] = useLocalStorage('name', '');
return (
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
);
}状态管理
Context API
适合中小型应用的状态管理。
// store.js
import { createContext, useContext, useReducer } from 'react';
const StoreContext = createContext();
const initialState = {
user: null,
cart: [],
};
function reducer(state, action) {
switch (action.type) {
case 'SET_USER':
return { ...state, user: action.payload };
case 'ADD_TO_CART':
return { ...state, cart: [...state.cart, action.payload] };
default:
return state;
}
}
export function StoreProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<StoreContext.Provider value={{ state, dispatch }}>
{children}
</StoreContext.Provider>
);
}
export function useStore() {
return useContext(StoreContext);
}Zustand(推荐)
轻量级状态管理库。
npm install zustandimport { create } from 'zustand';
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));
function Counter() {
const { count, increment, decrement } = useStore();
return (
<div>
<p>{count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}路由
React Router
npm install react-router-domimport { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Link to="/users">用户</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<UserDetail />} />
</Routes>
</BrowserRouter>
);
}数据获取
使用 fetch
function Posts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('/api/posts')
.then(res => res.json())
.then(data => {
setPosts(data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, []);
if (loading) return <div>加载中...</div>;
if (error) return <div>错误: {error}</div>;
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}使用 TanStack Query(推荐)
npm install @tanstack/react-queryimport { useQuery } from '@tanstack/react-query';
function Posts() {
const { data, isLoading, error } = useQuery({
queryKey: ['posts'],
queryFn: () => fetch('/api/posts').then(res => res.json()),
});
if (isLoading) return <div>加载中...</div>;
if (error) return <div>错误: {error.message}</div>;
return (
<ul>
{data.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}性能优化
1. React.memo
防止不必要的重新渲染。
const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
// 只有当 data 改变时才重新渲染
return <div>{/* 复杂的渲染逻辑 */}</div>;
});2. 代码分割
使用动态导入减少初始加载时间。
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>加载中...</div>}>
<HeavyComponent />
</Suspense>
);
}3. 虚拟化长列表
npm install react-windowimport { FixedSizeList } from 'react-window';
function VirtualList({ items }) {
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{({ index, style }) => (
<div style={style}>
{items[index]}
</div>
)}
</FixedSizeList>
);
}最佳实践
1. 组件设计
- 保持组件小而专注
- 使用组合而非继承
- 提取可复用的逻辑到自定义 Hook
2. 状态管理
- 状态尽可能放在最近的共同父组件
- 避免不必要的全局状态
- 使用 Context 或状态管理库管理复杂状态
3. 性能
- 使用 React DevTools Profiler 分析性能
- 避免在渲染函数中创建新对象/函数
- 合理使用 memo、useMemo、useCallback
4. 代码组织
src/
├── components/ # 可复用组件
├── pages/ # 页面组件
├── hooks/ # 自定义 Hooks
├── utils/ # 工具函数
├── services/ # API 调用
├── store/ # 状态管理
└── types/ # TypeScript 类型常用库推荐
- UI 组件库:Shadcn UI, Material-UI, Ant Design
- 状态管理:Zustand, Jotai, Redux Toolkit
- 数据获取:TanStack Query, SWR
- 表单:React Hook Form, Formik
- 动画:Framer Motion, React Spring
- 图表:Recharts, Chart.js
总结
React 是现代前端开发的核心技能。掌握 React 可以让你:
- 构建高性能的单页应用
- 开发可维护的大型项目
- 使用 React Native 开发移动应用
- 加入庞大的 React 生态系统
开始你的 React 之旅,构建出色的用户界面!
