环境配置
TypeScript
npm create vite@latest my-app -- --template react-ts
npm install react-router-dom
npm run dev
第1章:React核心概念与JSX
1.1 什么是React?
React是构建用户界面的JavaScript库,采用组件化开发模式。
1.2 基础组件示例
TypeScript
import React, { useState } from "react";
interface SonProps {
name: string;
}
// 函数组件与Props
const Son = (props: SonProps) => {
return <h1>您好,{props.name}!</h1>
}
// 状态组件
const Counter = () => {
const [count, setCount] = useState(0);
return (
<>
<p>你点击我 {count} 次</p>
<button onClick={() => setCount(count + 1)}>点击我</button>
</>
)
}
第2章:组件化开发
2.1 函数组件 vs 类组件
TypeScript
// 函数组件
const GreetingFn: React.FC = () => {
return <p>Hello 我是函数组件</p>
}
// 类组件
class GreetingClass extends React.Component {
render() {
return <p>Hello 我是类组件</p>
}
}
2.2 组件通信
TypeScript
interface Props {
name: string;
age: number;
}
const GreetingFnProps: React.FC<Props> = (props: Props) => {
return <p>我叫{props.name},我今年{props.age}岁了</p>
}
2.3 状态管理对比
TypeScript
// 函数组件状态
const GreetingStateFn: React.FC = () => {
const [count, setCount] = useState(0);
return (
<>
<p>你点击了{count}次</p>
<button onClick={() => setCount(count + 1)}>点击</button>
</>
)
}
第3章:基本渲染
3.1 列表渲染
TypeScript
interface JobProps {
id: number;
title: string;
company: string;
}
const JobItem: React.FC<{ job: JobProps }> = ({ job }) => {
return <li>{job.id} -- {job.title} -- {job.company}</li>
}
const JobList: React.FC = () => {
const jobs = [
{ id: 1, title: '前端', company: '阿里' },
{ id: 2, title: '后端', company: '腾讯' },
];
return (
<ul>
{jobs.map(job => (
<JobItem key={job.id} job={job} />
))}
</ul>
);
}
第4章:条件循环渲染
4.1 条件渲染示例
TypeScript
const UserList: React.FC = () => {
const [users, setUsers] = useState([
{ id: 1, name: '小王1', age: 18 },
{ id: 2, name: '小王2', age: 20 },
]);
const [showList, setShowList] = useState(true);
return (
<>
<button onClick={() => setShowList(!showList)}>
{showList ? '隐藏列表' : '显示列表'}
</button>
{showList && (
<ul>
{users.map(user => (
user.age > 18 ? (
<li style={{ color: 'red' }} key={user.id}>
{user.name} -- {user.age}
</li>
) : (
<li style={{ color: 'green' }} key={user.id}>
{user.name} -- {user.age}
</li>
)
))}
</ul>
)}
</>
);
}
第5章:受控文本输入框
5.1 基础输入控制
TypeScript
const Input1: React.FC = () => {
const [text, setText] = useState('');
return (
<>
<input value={text} onChange={(e) => setText(e.target.value)} />
<p>你输入的是:{text}</p>
</>
)
}
5.2 登录表单
TypeScript
const LoginForm: React.FC = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (e: any) => {
e.preventDefault();
console.log(username, password);
setUsername('');
setPassword('');
}
return (
<form onSubmit={handleSubmit}>
<input onChange={(e) => setUsername(e.target.value)} placeholder="用户名" />
<input onChange={(e) => setPassword(e.target.value)} placeholder="密码" />
<button>登录</button>
</form>
)
}
第6章:useState Hook
6.1 基础计数器
TypeScript
const Counter: React.FC = () => {
const [count, setCount] = useState<number>(0);
return (
<>
<button disabled={count <= 0} onClick={() => setCount(count - 1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</>
)
}
6.2 带参数的计数器
TypeScript
interface CounterProps {
number: number
}
const CounterNumber: React.FC<CounterProps> = ({ number }) => {
const [count, setCount] = useState<number>(0);
return (
<>
<button onClick={() => setCount(count - number)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + number)}>+</button>
</>
)
}
第7章:useEffect Hook
7.1 副作用处理
TypeScript
const Greeting: React.FC<{ name: string }> = ({ name }) => {
const [message, setMessage] = useState<string>('');
useEffect(() => {
console.log('useEffect is running.....');
setMessage(`Hello ${name}!`);
return () => {
console.log('Cleanup function is running...');
};
}, [name]);
return <h1>{message}</h1>
}
第8章:useContext Hook
8.1 Context状态管理
TypeScript
interface AuthContextType {
isAuthenticated: boolean;
login: () => void;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
const login = () => {
setIsAuthenticated(true);
console.log("登录成功");
};
const logout = () => {
setIsAuthenticated(false);
console.log("登出成功");
};
return (
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};
第9章:useReducer Hook
9.1 复杂状态管理
TypeScript
interface CounterState {
count: number;
}
type CounterAction =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'reset' }
| { type: 'set'; payload: number };
const counterReducer = (state: CounterState, action: CounterAction): CounterState => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
case 'set':
return { count: action.payload };
default:
return state;
}
};
const Counter: React.FC = () => {
const [state, dispatch] = useReducer(counterReducer, { count: 0 });
return (
<div>
<p>当前计数:{state.count}</p>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'reset' })}>重置</button>
</div>
);
};
第10章:useCallback Hook
10.1 性能优化
const ExpensiveButton = memo(({ onClick, label }: { onClick: () => void; label: string }) => {
console.log(`${label} 按钮渲染了`);
return <button onClick={onClick}>{label}</button>;
});
const WithUseCallback: React.FC = () => {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return (
<div>
<p>计数:{count}</p>
<p>其他状态:{otherState}</p>
<ExpensiveButton onClick={handleClick} label="增加计数" />
<button onClick={() => setOtherState(s => s + 1)}>改变其他状态</button>
</div>
);
};
第11章:useMemo Hook
11.1 缓存计算结果
const expensiveCalculation = (num: number): number => {
console.log('执行耗时计算...');
let result = 0;
for (let i = 0; i < 1000000000; i++) {
result += num;
}
return result;
};
const WithUseMemo: React.FC = () => {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
const expensiveValue = useMemo(() => {
return expensiveCalculation(count);
}, [count]);
return (
<div>
<p>计算结果:{expensiveValue}</p>
<p>其他状态:{otherState}</p>
<button onClick={() => setCount(c => c + 1)}>增加计数</button>
<button onClick={() => setOtherState(s => s + 1)}>改变其他状态(不会触发计算)</button>
</div>
);
};
第12章:useRef Hook
12.1 访问DOM元素
TypeScript
const FocusInput: React.FC = () => {
const inputRef = useRef<HTMLInputElement>(null);
const handleFocus = () => {
inputRef.current?.focus();
};
return (
<div>
<input ref={inputRef} placeholder="点击按钮聚焦" />
<button onClick={handleFocus}>聚焦输入框</button>
</div>
);
};
12.2 定时器管理
TypeScript
const Timer: React.FC = () => {
const [seconds, setSeconds] = useState(0);
const [isRunning, setIsRunning] = useState(false);
const intervalRef = useRef<number | null>(null);
const start = () => {
if (!isRunning) {
setIsRunning(true);
intervalRef.current = window.setInterval(() => {
setSeconds(s => s + 1);
}, 1000);
}
};
const stop = () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
setIsRunning(false);
}
};
return (
<div>
<p>时间:{seconds} 秒</p>
<button onClick={start} disabled={isRunning}>开始</button>
<button onClick={stop} disabled={!isRunning}>停止</button>
</div>
);
};
第13章:自定义Hooks
13.1 useLocalStorage
TypeScript
function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T) => void] {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});
const setValue = (value: T) => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};
return [storedValue, setValue];
}
13.2 useFetch
TypeScript
interface UseFetchReturn<T> {
data: T | null;
loading: boolean;
error: string | null;
refetch: () => void;
}
function useFetch<T>(url: string): UseFetchReturn<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(url);
if (!response.ok) throw new Error('请求失败');
const result = await response.json();
setData(result);
} catch (err) {
setError(err instanceof Error ? err.message : '未知错误');
} finally {
setLoading(false);
}
}, [url]);
useEffect(() => {
fetchData();
}, [fetchData]);
return { data, loading, error, refetch: fetchData };
}
第14章:React Router
14.1 路由配置
TypeScript
import { BrowserRouter, Routes, Route, Link, useParams, useNavigate } from "react-router-dom";
const UserDetail: React.FC = () => {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
return (
<div>
<h3>用户详情</h3>
<p>用户 ID:{id}</p>
<button onClick={() => navigate('/users')}>返回列表</button>
</div>
);
};
const App: React.FC = () => {
return (
<BrowserRouter>
<nav>
<Link to="/">首页</Link>
<Link to="/users">用户</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users/:id" element={<UserDetail />} />
</Routes>
</BrowserRouter>
);
};
第15章:数据获取与管理
15.1 基础数据获取
TypeScript
const BasicFetch: React.FC = () => {
const [posts, setPosts] = useState<Post[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchPosts = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
if (!response.ok) throw new Error('请求失败');
const data = await response.json();
setPosts(data);
} catch (err) {
setError(err instanceof Error ? err.message : '未知错误');
} finally {
setLoading(false);
}
};
fetchPosts();
}, []);
if (loading) return <p>加载中...</p>;
if (error) return <p style={{ color: 'red' }}>错误:{error}</p>;
return (
<ul>
{posts.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
);
};
第16章:表单处理与验证
16.1 完整表单示例
TypeScript
interface FormData {
username: string;
email: string;
password: string;
confirmPassword: string;
}
const validateForm = (data: FormData) => {
const errors: any = {};
if (!data.username.trim()) {
errors.username = '用户名不能为空';
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
errors.email = '邮箱格式不正确';
}
if (data.password !== data.confirmPassword) {
errors.confirmPassword = '两次密码不一致';
}
return errors;
};
const RegistrationForm: React.FC = () => {
const [formData, setFormData] = useState<FormData>({
username: '',
email: '',
password: '',
confirmPassword: ''
});
const [errors, setErrors] = useState<any>({});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const validationErrors = validateForm(formData);
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
console.log('表单数据:', formData);
}
};
return (
<form onSubmit={handleSubmit}>
<input name="username" value={formData.username} onChange={handleChange} placeholder="用户名" />
{errors.username && <p style={{color: 'red'}}>{errors.username}</p>}
<input name="email" value={formData.email} onChange={handleChange} placeholder="邮箱" />
{errors.email && <p style={{color: 'red'}}>{errors.email}</p>}
<button type="submit">注册</button>
</form>
);
};
第17章:状态管理方案
17.1 Context + useReducer
TypeScript
interface AppState {
user: User | null;
cart: CartItem[];
theme: 'light' | 'dark';
}
type AppAction =
| { type: 'LOGIN'; payload: User }
| { type: 'LOGOUT' }
| { type: 'ADD_TO_CART'; payload: CartItem }
| { type: 'TOGGLE_THEME' };
const appReducer = (state: AppState, action: AppAction): AppState => {
switch (action.type) {
case 'LOGIN':
return { ...state, user: action.payload };
case 'LOGOUT':
return { ...state, user: null };
case 'ADD_TO_CART':
return { ...state, cart: [...state.cart, action.payload] };
case 'TOGGLE_THEME':
return { ...state, theme: state.theme === 'light' ? 'dark' : 'light' };
default:
return state;
}
};
const AppProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [state, dispatch] = useReducer(appReducer, initialState);
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
);
};
第18章:性能优化技巧
18.1 React.memo优化
TypeScript
const ExpensiveChild = memo(({ value, onClick }: { value: number; onClick: () => void }) => {
console.log('ExpensiveChild 渲染了');
return (
<div>
<p>值:{value}</p>
<button onClick={onClick}>点击</button>
</div>
);
});
const Parent = () => {
const [count, setCount] = useState(0);
const [otherState, setOtherState] = useState(0);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return (
<div>
<ExpensiveChild value={count} onClick={handleClick} />
<button onClick={() => setOtherState(s => s + 1)}>改变其他状态</button>
</div>
);
};
第19章:Hooks最佳实践
19.1 正确处理useEffect依赖
TypeScript
const UseEffectDependencies: React.FC = () => {
const [count, setCount] = useState(0);
// 正确:包含所有依赖
useEffect(() => {
console.log('count 变化了:', count);
}, [count]);
// 使用函数式更新避免依赖
useEffect(() => {
const timer = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
return <p>计数:{count}</p>;
};
19.2 清理副作用
TypeScript
const CleanupDemo: React.FC = () => {
const [isSubscribed, setIsSubscribed] = useState(false);
useEffect(() => {
if (!isSubscribed) return;
const handleResize = () => console.log('窗口大小变化');
window.addEventListener('resize', handleResize);
return () => {
console.log('取消订阅');
window.removeEventListener('resize', handleResize);
};
}, [isSubscribed]);
return (
<div>
<button onClick={() => setIsSubscribed(!isSubscribed)}>
{isSubscribed ? '取消订阅' : '订阅'} resize 事件
</button>
</div>
);
};
核心要点总结
最佳实践
-
类型安全:始终为组件Props定义TypeScript接口
-
性能优化:合理使用memo、useCallback、useMemo
-
状态管理:简单状态用useState,复杂状态用useReducer
-
副作用处理:正确设置useEffect依赖,记得清理
-
自定义Hooks:抽取复用逻辑,提高代码可维护性
常见错误
-
不要在条件语句中调用Hooks
-
不要忘记useEffect的清理函数
-
不要过度优化(memo、useCallback)
-
不要在render中创建对象或数组
🔗 学习资源
本教程基于实际项目的19个文件编写,每个示例都经过验证可以直接使用。从React基础到高级特性,从Hooks到性能优化,全面覆盖现代React开发所需技能。
觉得有用请点赞收藏分享!