大家好,我是鱼樱!!!
关注公众号【鱼樱AI实验室】
持续每天分享更多前端和AI辅助前端编码新知识~~喜欢的就一起学反正开源至上,无所谓被诋毁被喷被质疑文章没有价值~~~坚持自己观点
一个城市淘汰的自由职业-农村前端程序员(虽然不靠代码挣钱,写文章就是为爱发电),兼职远程上班目前!!!热心坚持分享~~~
今天为大家分享一份React完整学习指南仅供参考学习方向和思路~
目录
- 第一部分:React基础知识
- 第二部分:React版本演进(16-19)
- 第三部分:组件与Props
- 第四部分:状态管理
- 第五部分:生命周期方法
- 第六部分:React Hooks基础
- 第七部分:常用Hooks详解
- 第八部分:自定义Hooks开发
- 第九部分:第三方Hooks库
- 第十部分:性能优化策略
- 第十一部分:TypeScript最佳实践
- React性能优化深度指南
- 状态管理全面指南:Redux/MobX/Zustand最佳实践
- 结语:React学习路径推荐
第一部分:React基础知识
1.1 React简介
React是由Facebook开发的声明式UI库,主要用于构建用户界面。它的核心思想是:
- 组件化开发:将UI拆分为独立、可复用的小组件
- 单向数据流:数据从父组件流向子组件
- 虚拟DOM:提高渲染性能
1.2 搭建React开发环境
使用Create React App
sh
npx create-react-app my-app
cd my-app
npm start
使用Vite(更现代的构建工具)
sh
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
1.3 JSX基础
JSX是JavaScript的语法扩展,让你在JavaScript中编写类似HTML的代码。
tsx
// JSX语法示例
const element = <h1>Hello, world!</h1>;
// 使用表达式
const name = "React";
const element = <h1>Hello, {name}!</h1>;
// 多行JSX需要用括号包裹
const element = (
<div>
<h1>Hello!</h1>
<p>Welcome to React</p>
</div>
);
JSX的关键特性:
- JSX会被Babel编译为
React.createElement()
调用 - JSX中使用camelCase命名属性 ,如
className
而不是class
- JSX中可以嵌入JavaScript表达式,使用
{}
包裹 - JSX本身也是表达式,可以在JS逻辑中使用
第二部分:React版本演进(16-19)
2.1 React 16的主要特性
- Fiber架构 :完全重写的核心算法,支持增量渲染
- Error Boundaries:更好的错误处理
- Portals:将子节点渲染到DOM树的不同位置
- 服务端渲染改进
- 支持自定义DOM属性
2.2 React 17的主要特性
- 无新特性:这是一个过渡版本
- 事件委托系统改变:从document变为React树的根DOM容器
- 更好的JSX转换:不再需要导入React
- 渐进式升级支持:可以在同一页面运行多个React版本
2.3 React 18的主要特性
- 并发渲染:React可以准备多个UI版本同时存在
- 自动批处理:多个状态更新会被批处理
- Suspense SSR:流式服务端渲染
- 新的Root API :
ReactDOM.createRoot()
- 新的Hooks :
useId
,useTransition
,useDeferredValue
2.4 React 19的主要特性
- Actions:组件级别的数据获取和修改
- Compiler优化:专门针对React的编译优化
- React Forget:自动记忆化
- 文档组件支持:更好的服务器组件支持
- React Hooks改进:更好的调试体验
第三部分:组件与Props
3.1 函数组件
tsx
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
3.2 类组件
tsx
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
3.3 组件组合
组合组件是React的强大特性,可以构建复杂UI:
tsx
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
3.4 Props的特性
- Props是只读的,不应该修改它们
- Props可以传递任何JavaScript值,包括函数和JSX
- 可以使用解构来简化代码
tsx
function Welcome({ name, age }) {
return <h1>Hello, {name}, you are {age} years old</h1>;
}
第四部分:状态管理
4.1 类组件中的状态
tsx
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
4.2 使用useState Hook
tsx
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
4.3 状态更新注意事项
- 状态更新可能是异步的
- 状态更新会合并 (类组件)或替换(函数组件)之前的状态
- 依赖之前的状态时,应该使用函数形式
tsx
// 类组件
this.setState(prevState => ({ count: prevState.count + 1 }));
// 函数组件
setCount(prevCount => prevCount + 1);
第五部分:生命周期方法
5.1 React 16.3之前的生命周期
类组件的生命周期可分为三个阶段:
挂载阶段:
constructor()
- 初始化state和绑定方法componentWillMount()
(已废弃)render()
- 返回需要渲染的元素componentDidMount()
- 组件挂载后执行,适合网络请求
更新阶段:
componentWillReceiveProps(nextProps)
(已废弃)shouldComponentUpdate(nextProps, nextState)
- 决定是否重新渲染componentWillUpdate(nextProps, nextState)
(已废弃)render()
componentDidUpdate(prevProps, prevState)
- 更新后执行
卸载阶段:
componentWillUnmount()
- 组件卸载前执行清理工作
5.2 React 16.3及之后的生命周期
React 16.3引入了新的生命周期方法,废弃一些旧方法:
新增的生命周期方法:
getDerivedStateFromProps(props, state)
- 替代componentWillReceiveProps
getSnapshotBeforeUpdate(prevProps, prevState)
- 在DOM更新前捕获信息
废弃的生命周期方法(带UNSAFE_前缀):
UNSAFE_componentWillMount()
UNSAFE_componentWillReceiveProps()
UNSAFE_componentWillUpdate()
tsx
class ExampleComponent extends React.Component {
// 挂载阶段
constructor(props) {
super(props);
this.state = { data: [] };
}
static getDerivedStateFromProps(props, state) {
// 返回新状态或null
return null;
}
componentDidMount() {
// API调用等初始化操作
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => this.setState({ data }));
}
// 更新阶段
shouldComponentUpdate(nextProps, nextState) {
// 性能优化:控制组件是否需要重新渲染
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// 在DOM更新前捕获信息(如滚动位置)
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// 使用snapshot更新DOM
if (this.props.id !== prevProps.id) {
// props变化后的操作
}
}
// 卸载阶段
componentWillUnmount() {
// 清理操作:取消订阅、定时器等
}
render() {
return <div>{this.state.data.map(item => <div key={item.id}>{item.name}</div>)}</div>;
}
}
5.3 类组件生命周期与Hooks对应关系
类组件生命周期 | Hooks对应方案 |
---|---|
constructor | useState初始化 |
componentDidMount | useEffect(() => {}, []) |
componentDidUpdate | useEffect(() => {}, [dependencies]) |
componentWillUnmount | useEffect(() => { return () => {} }, []) |
shouldComponentUpdate | React.memo + useMemo/useCallback |
getDerivedStateFromProps | useState + useEffect |
第六部分:React Hooks基础
6.1 Hooks简介
Hooks 是React 16.8引入的特性,让你在不编写类组件的情况下使用状态和其他React特性。
Hooks的优势:
- 更好的逻辑复用
- 减少复杂组件的嵌套(告别HOC和render props)
- 更简洁的代码
- 更容易理解的组件行为
Hooks使用规则:
- 只能在函数组件 或自定义Hook中调用
- 只能在顶层调用,不能在条件语句、循环或嵌套函数中调用
- 函数名必须以use开头
6.2 useState - 状态管理
tsx
import { useState } from 'react';
function Counter() {
// 声明一个状态变量和更新函数
const [count, setCount] = useState(0);
// 使用对象状态
const [user, setUser] = useState({ name: '', age: 0 });
// 更新对象状态(需要合并之前的状态)
const updateName = (name) => {
setUser(prevUser => ({ ...prevUser, name }));
};
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>Safe Increment</button>
<input
value={user.name}
onChange={e => updateName(e.target.value)}
/>
</div>
);
}
6.3 useEffect - 副作用处理
tsx
import { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
// 组件挂载后获取数据
useEffect(() => {
const fetchData = async () => {
try {
setIsLoading(true);
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
};
fetchData();
// 清理函数(相当于componentWillUnmount)
return () => {
// 取消请求、清除定时器等
};
}, []); // 空依赖数组表示只在挂载和卸载时执行
// 依赖特定值变化的effect
useEffect(() => {
document.title = `You have ${data.length} items`;
}, [data]); // 当data变化时执行
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
6.4 useContext - 上下文管理
tsx
import { createContext, useContext, useState } from 'react';
// 创建上下文
const ThemeContext = createContext('light');
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={theme}>
<div>
<ThemedButton />
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
</div>
</ThemeContext.Provider>
);
}
function ThemedButton() {
// 使用上下文
const theme = useContext(ThemeContext);
return (
<button style={{
background: theme = 'light' ? '#fff' : '#333',
color: theme = 'light' ? '#333' : '#fff'
}}>
I am styled by theme context!
</button>
);
}
第七部分:常用Hooks详解
7.1 useReducer - 复杂状态管理
适用场景:当状态逻辑复杂、涉及多个子值或下一个状态依赖前一个状态时。
tsx
import { useReducer } from 'react';
// 定义reducer函数
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
throw new Error('Unknown action');
}
}
function Counter() {
// 使用reducer
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}
7.2 useRef - 引用DOM和保存变量
useRef有两个主要用途:
- 访问DOM元素
- 在渲染间保持值(不触发重新渲染)
tsx
import { useRef, useEffect, useState } from 'react';
function TextInputWithFocus() {
// 创建ref
const inputRef = useRef(null);
const renderCountRef = useRef(0);
const [text, setText] = useState('');
// 焦点到input元素
const focusInput = () => {
inputRef.current.focus();
};
// 追踪组件渲染次数
useEffect(() => {
renderCountRef.current += 1;
console.log(`Rendered ${renderCountRef.current} times`);
});
return (
<div>
<input
ref={inputRef}
value={text}
onChange={e => setText(e.target.value)}
/>
<button onClick={focusInput}>Focus Input</button>
<p>Component rendered {renderCountRef.current} times</p>
</div>
);
}
7.3 useMemo - 记忆计算结果
用途:缓存计算结果,避免在每次渲染时重复进行昂贵的计算。
tsx
import { useState, useMemo } from 'react';
function ExpensiveCalculation({ list, filter }) {
// 使用useMemo缓存计算结果
const filteredList = useMemo(() => {
console.log("Computing filtered list...");
return list.filter(item => item.includes(filter));
}, [list, filter]); // 只有当list或filter变化时才重新计算
return (
<div>
<p>Filtered list length: {filteredList.length}</p>
<ul>
{filteredList.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
function App() {
const [filter, setFilter] = useState('');
const [list] = useState(['apple', 'banana', 'cherry', 'date', 'elderberry']);
return (
<div>
<input
value={filter}
onChange={e => setFilter(e.target.value)}
placeholder="Filter fruits..."
/>
<ExpensiveCalculation list={list} filter={filter} />
</div>
);
}
7.4 useCallback - 记忆函数
用途:缓存函数引用,避免子组件不必要的重新渲染。
tsx
import { useState, useCallback } from 'react';
// 子组件使用React.memo优化
const Button = React.memo(({ onClick, children }) => {
console.log(`Rendering button: ${children}`);
return <button onClick={onClick}>{children}</button>;
});
function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
// 不使用useCallback的函数,每次渲染都会创建新的函数引用
const incrementWithoutCallback = () => {
setCount(c => c + 1);
};
// 使用useCallback缓存函数引用
const incrementWithCallback = useCallback(() => {
setCount(c => c + 1);
}, []); // 空依赖数组表示函数引用永不变化
return (
<div>
<p>Count: {count}</p>
<input
value={text}
onChange={e => setText(e.target.value)}
placeholder="Type to trigger re-render"
/>
{/* 每次父组件重新渲染,这个按钮也会重新渲染 */}
<Button onClick={incrementWithoutCallback}>
Increment (without useCallback)
</Button>
{/* 这个按钮不会在父组件重新渲染时重新渲染 */}
<Button onClick={incrementWithCallback}>
Increment (with useCallback)
</Button>
</div>
);
}
7.5 React 18新增的Hooks
useId - 生成唯一ID
tsx
import { useId } from 'react';
function LabeledInput() {
const id = useId();
return (
<div>
<label htmlFor={id}>Email</label>
<input id={id} type="email" />
</div>
);
}
useTransition - 非阻塞更新
tsx
import { useState, useTransition } from 'react';
function SearchResults() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
// 立即更新输入框(高优先级)
setQuery(e.target.value);
// 在transition中更新搜索结果(低优先级)
startTransition(() => {
// 假设这是一个昂贵的操作
const searchResults = performExpensiveSearch(e.target.value);
setResults(searchResults);
});
};
return (
<div>
<input value={query} onChange={handleChange} />
{isPending ? (
<p>Loading results...</p>
) : (
<ul>
{results.map(result => <li key={result.id}>{result.name}</li>)}
</ul>
)}
</div>
);
}
useDeferredValue - 延迟值更新
tsx
import { useState, useDeferredValue } from 'react';
function SearchResults() {
const [query, setQuery] = useState('');
// 创建一个延迟值
const deferredQuery = useDeferredValue(query);
// 使用延迟值进行昂贵的计算
const results = performExpensiveSearch(deferredQuery);
// UI会立即响应输入,但搜索结果会使用延迟值
return (
<div>
<input value={query} onChange={e => setQuery(e.target.value)} />
{deferredQuery !== query && <p>Loading...</p>}
<ul>
{results.map(result => <li key={result.id}>{result.name}</li>)}
</ul>
</div>
);
}
第八部分:自定义Hooks开发
8.1 自定义Hooks基础
自定义Hooks是一种复用有状态逻辑的方式,本质上是抽取组件逻辑到可重用的函数中。
自定义Hook特点:
- 函数名必须以use开头
- 可以调用其他Hooks
- 返回任何需要的值
tsx
// 自定义Hook:管理表单字段
function useFormField(initialValue = '') {
const [value, setValue] = useState(initialValue);
const [error, setError] = useState('');
const handleChange = (e) => {
setValue(e.target.value);
if (e.target.value.trim() === '') {
setError('This field is required');
} else {
setError('');
}
};
return {
value,
error,
onChange: handleChange,
reset: () => setValue(initialValue),
};
}
// 使用自定义Hook
function SignupForm() {
const username = useFormField('');
const email = useFormField('');
const password = useFormField('');
const handleSubmit = (e) => {
e.preventDefault();
// 表单提交逻辑
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Username</label>
<input type="text" {...username} />
{username.error && <p>{username.error}</p>}
</div>
<div>
<label>Email</label>
<input type="email" {...email} />
{email.error && <p>{email.error}</p>}
</div>
<div>
<label>Password</label>
<input type="password" {...password} />
{password.error && <p>{password.error}</p>}
</div>
<button type="submit">Sign Up</button>
</form>
);
}
8.2 常用自定义Hooks示例
useLocalStorage - 本地存储状态
tsx
function useLocalStorage(key, initialValue) {
// 读取初始值
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
// 更新值并存储到localStorage
const setValue = (value) => {
try {
// 处理函数形式的value
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue];
}
// 使用示例
function App() {
const [name, setName] = useLocalStorage('name', '');
return (
<div>
<input
value={name}
onChange={e => setName(e.target.value)}
placeholder="Enter your name"
/>
<p>Hello, {name || 'Guest'}!</p>
</div>
);
}
useFetch - 数据获取
tsx
function useFetch(url) {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let isMounted = true;
const controller = new AbortController();
async function fetchData() {
setIsLoading(true);
try {
const response = await fetch(url, { signal: controller.signal });
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const json = await response.json();
if (isMounted) {
setData(json);
setError(null);
}
} catch (err) {
if (err.name !== 'AbortError' && isMounted) {
setError(err.message);
setData(null);
}
} finally {
if (isMounted) {
setIsLoading(false);
}
}
}
fetchData();
return () => {
isMounted = false;
controller.abort();
};
}, [url]);
return { data, isLoading, error };
}
// 使用示例
function UserProfile({ userId }) {
const { data, isLoading, error } = useFetch(`https://api.example.com/users/${userId}`);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!data) return null;
return (
<div>
<h1>{data.name}</h1>
<p>Email: {data.email}</p>
</div>
);
}
第九部分:第三方Hooks库
9.1 ahooks - 阿里巴巴开源Hooks库
特点:
- 全面的Hooks集合
- 高质量、高性能
- 覆盖常见业务场景
常用Hooks示例:
tsx
// useRequest - 强大的数据请求管理Hook
import { useRequest } from 'ahooks';
function UserList() {
const { data, loading, error, run } = useRequest(fetchUserList, {
manual: true,
// 请求防抖
debounceInterval: 500,
// 错误重试
retryCount: 3,
// 轮询配置
pollingInterval: 5000
});
return (
<div>
<button onClick={run}>获取用户列表</button>
{loading && <p>加载中...</p>}
{error && <p>请求错误</p>}
{data && (
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
);
}
// useEventListener - 事件监听
import { useEventListener } from 'ahooks';
function KeyboardTracker() {
const [key, setKey] = useState('');
useEventListener('keydown', (event: KeyboardEvent) => {
setKey(event.key);
});
return <div>Last pressed key: {key}</div>;
}
// useLocalStorageState - 带持久化的状态管理
import { useLocalStorageState } from 'ahooks';
function PersistentCounter() {
const [count, setCount] = useLocalStorageState('count', {
defaultValue: 0
});
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
</div>
);
}
9.2 react-use - 全面的Hooks工具库
特点:
- 100+个实用Hooks
- 覆盖DOM、浏览器、传感器等场景
tsx
import {
useMedia,
useNetworkState,
useFullscreen,
useCopyToClipboard
} from 'react-use';
function ResponsiveComponent() {
// 响应式媒体查询
const isWide = useMedia('(min-width: 1200px)');
// 网络状态监听
const state = useNetworkState();
// 全屏控制
const [show, setShow] = useState(false);
const ref = useRef(null);
const isFullscreen = useFullscreen(ref, show, {
onEnter: () => console.log('进入全屏'),
onExit: () => console.log('退出全屏')
});
// 剪贴板操作
const [copied, copyToClipboard] = useCopyToClipboard();
return (
<div ref={ref}>
<p>屏幕宽度: {isWide ? '宽屏' : '窄屏'}</p>
<p>网络状态: {state.online ? '在线' : '离线'}</p>
<button onClick={() => setShow(!show)}>
{isFullscreen ? '退出全屏' : '进入全屏'}
</button>
<button onClick={() => copyToClipboard('复制的文本')}>
复制文本
</button>
{copied.value && <p>已复制!</p>}
</div>
);
}
9.3 自定义高级Hooks
useAsync - 通用异步处理
tsx
function useAsync<T>(
asyncFunction: () => Promise<T>,
immediate = true
) {
const [status, setStatus] = useState<'idle' | 'pending' | 'success' | 'error'>('idle');
const [value, setValue] = useState<T | null>(null);
const [error, setError] = useState<Error | null>(null);
const execute = useCallback(() => {
setStatus('pending');
setValue(null);
setError(null);
return asyncFunction()
.then(response => {
setValue(response);
setStatus('success');
})
.catch(error => {
setError(error);
setStatus('error');
});
}, [asyncFunction]);
useEffect(() => {
if (immediate) {
execute();
}
}, [execute, immediate]);
return { execute, status, value, error };
}
// 使用示例
function UserProfile() {
const fetchUser = async () => {
const response = await fetch('/api/user');
return response.json();
};
const { status, value, error, execute } = useAsync(fetchUser);
if (status = 'pending') return <div>Loading...</div>;
if (status = 'error') return <div>Error: {error?.message}</div>;
return (
<div>
<h1>{value?.name}</h1>
<button onClick={execute}>Refresh</button>
</div>
);
}
9.4 响应式状态管理Hooks
useImmer - 不可变状态更新
tsx
import produce from 'immer';
import { useImmer } from 'use-immer';
interface User {
name: string;
age: number;
tags: string[];
}
function UserManager() {
const [user, updateUser] = useImmer<User>({
name: 'John',
age: 30,
tags: ['developer']
});
const addTag = (tag: string) => {
updateUser(draft => {
draft.tags.push(tag);
});
};
const incrementAge = () => {
updateUser(draft => {
draft.age += 1;
});
};
return (
<div>
<p>Name: {user.name}</p>
<p>Age: {user.age}</p>
<p>Tags: {user.tags.join(', ')}</p>
<button onClick={() => addTag('programmer')}>
Add Tag
</button>
<button onClick={incrementAge}>
Increment Age
</button>
</div>
);
}
第十部分:性能优化策略
10.1 渲染性能优化
1. React.memo - 组件记忆
tsx
const ExpensiveComponent = React.memo(({ id, name }) => {
console.log('Rendering expensive component');
return <div>{name}</div>;
}, (prevProps, nextProps) => {
// 自定义比较逻辑
return prevProps.id === nextProps.id;
});
2. useMemo - 计算缓存
tsx
function DataProcessor({ data }) {
const processedData = useMemo(() => {
return data.map(item => expensiveComputation(item));
}, [data]);
return <div>{processedData.length}</div>;
}
3. useCallback - 函数缓存
tsx
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
10.2 代码分割
tsx
// 动态导入
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
10.3 虚拟列表优化
tsx
import { FixedSizeList } from 'react-window';
function LargeList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
{items[index]}
</div>
);
return (
<FixedSizeList
height={400}
itemCount={items.length}
itemSize={35}
width={300}
>
{Row}
</FixedSizeList>
);
}
第十一部分:TypeScript最佳实践
11.1 函数组件类型
tsx
interface Props {
name: string;
age?: number;
children?: React.ReactNode;
}
// 函数组件类型
const Greeter: React.FC<Props> = ({ name, age = 0 }) => {
return <div>Hello {name}, {age} years old</div>;
};
// 现代推荐写法
function Greeter({ name, age = 0 }: Props) {
return <div>Hello {name}, {age} years old</div>;
}
11.2 Hooks类型
tsx
function useCustomHook<T>(initialValue: T): [T, (value: T) => void] {
const [state, setState] = useState<T>(initialValue);
return [state, setState];
}
React性能优化深度指南
1. 渲染性能优化策略
1.1 组件渲染优化
tsx
// 使用React.memo进行浅比较
interface UserProps {
name: string;
age: number;
}
const UserCard = React.memo<UserProps>((props) => {
console.log('渲染UserCard');
return (
<div>
<h2>{props.name}</h2>
<p>Age: {props.age}</p>
</div>
);
}, (prevProps, nextProps) => {
// 自定义比较逻辑
return (
prevProps.name = nextProps.name &&
prevProps.age = nextProps.age
);
});
// 复杂对象的性能比较
const areEqual = (prevProps: UserProps, nextProps: UserProps) => {
return (
prevProps.name = nextProps.name &&
prevProps.age = nextProps.age
);
};
const MemoizedUserCard = React.memo(UserCard, areEqual);
1.2 useMemo性能优化
tsx
function ExpensiveComponent({ data }: { data: number[] }) {
// 仅在data变化时重新计算
const processedData = useMemo(() => {
console.log('计算处理数据');
return data.map(item => {
// 复杂计算逻辑
return item * 2;
});
}, [data]);
return (
<div>
{processedData.map(item => (
<div key={item}>{item}</div>
))}
</div>
);
}
// 多依赖项的useMemo
function ComplexCalculation({ a, b, c }) {
const result = useMemo(() => {
return heavyCalculation(a, b, c);
}, [a, b, c]);
return <div>{result}</div>;
}
1.3 useCallback函数记忆
tsx
interface SearchProps {
onSearch: (query: string) => void;
}
const SearchComponent = React.memo(({ onSearch }: SearchProps) => {
const [query, setQuery] = useState('');
// 使用useCallback缓存函数
const handleSearch = useCallback(() => {
onSearch(query);
}, [query, onSearch]);
return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<button onClick={handleSearch}>搜索</button>
</div>
);
});
function ParentComponent() {
// 使用useCallback避免不必要的重渲染
const searchHandler = useCallback((query: string) => {
console.log('搜索:', query);
}, []);
return <SearchComponent onSearch={searchHandler} />;
}
2. 代码分割与懒加载
tsx
// 动态导入组件
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
// 路由级懒加载
function Router() {
return (
<Suspense fallback={<Loader />}>
<Routes>
<Route
path="/dashboard"
element={
<React.Suspense fallback={<Loader />}>
<Dashboard />
</React.Suspense>
}
/>
</Routes>
</Suspense>
);
}
3. 虚拟列表优化
tsx
import { FixedSizeList as List } from 'react-window';
import AutoSizer from 'react-virtualized-auto-sizer';
interface ItemData {
id: number;
name: string;
}
function VirtualizedList({ items }: { items: ItemData[] }) {
const Row = React.memo(({ index, style }: { index: number, style: React.CSSProperties }) => {
const item = items[index];
return (
<div style={style}>
{item.name}
</div>
);
});
return (
<AutoSizer>
{({ height, width }) => (
<List
height={height}
itemCount={items.length}
itemSize={50}
width={width}
>
{Row}
</List>
)}
</AutoSizer>
);
}
4. 性能监控与分析
tsx
// 性能追踪高阶组件
function withPerformanceTracker<P>(
WrappedComponent: React.ComponentType<P>
) {
return class extends React.Component<P> {
private startTime: number;
constructor(props: P) {
super(props);
this.startTime = performance.now();
}
componentDidMount() {
const renderTime = performance.now() - this.startTime;
console.log(
`Component ${WrappedComponent.name} 渲染耗时: ${renderTime}ms`
);
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}
// 使用性能追踪
const TrackedComponent = withPerformanceTracker(MyComponent);
5. TypeScript集成最佳实践
5.1 接口与类型定义
tsx
// 组件Props类型
interface UserProfileProps {
id: number;
name: string;
age?: number;
onUpdate?: (user: UserProfileProps) => void;
}
// 复杂泛型组件
function DataFetcher<T>({
fetchFn,
render
}: {
fetchFn: () => Promise<T>;
render: (data: T) => React.ReactNode;
}) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchFn().then(result => {
setData(result);
setLoading(false);
});
}, [fetchFn]);
return (
<>
{loading ? <Spinner /> : data && render(data)}
</>
);
}
5.2 Hooks类型定义
tsx
// 泛型自定义Hooks
function useLocalStorage<T>(
key: string,
initialValue: T
): [T, (value: T) => void] {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.log(error);
return initialValue;
}
});
const setValue = (value: T) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.log(error);
}
};
return [storedValue, setValue];
}
// 使用示例
function App() {
const [name, setName] = useLocalStorage<string>('name', '');
const [user, setUser] = useLocalStorage<UserProfileProps>('user', {
id: 1,
name: '',
age: undefined
});
}
5.3 高级类型技巧
tsx
// 条件渲染类型
type RenderProps<T> = {
data: T;
loading?: boolean;
} & (
| { loading: true; data?: never }
| { loading: false; data: T }
);
function ConditionalRenderer<T>({
data,
loading,
children
}: RenderProps<T> & {
children: (data: T) => React.ReactNode
}) {
if (loading) return <Spinner />;
return children(data);
}
// 使用示例
function App() {
const { data, loading } = useFetch<UserProfileProps>();
return (
<ConditionalRenderer
data={data}
loading={loading}
>
{(userData) => (
<UserProfile {...userData} />
)}
</ConditionalRenderer>
);
}
6. 性能优化最佳实践清单
- 使用
React.memo
减少不必要渲染 - 正确使用
useMemo
和useCallback
- 代码分割与懒加载
- 虚拟列表处理大数据
- 避免过深的组件树
- 减少不必要的props传递
- 使用
useReducer
管理复杂状态 - 合理设计状态提升策略
- 使用性能分析工具
性能分析工具:
- React DevTools
- Chrome Performance
- Lighthouse
- WebPageTest
持续优化的原则:
- 测量
- 优化
- 重复
加油,成为React性能大师! 🚀🔥
状态管理全面指南:Redux/MobX/Zustand最佳实践
1. Redux深度实践
1.1 现代Redux Toolkit实践
tsx
import { createSlice, configureStore, PayloadAction } from '@reduxjs/toolkit';
// 定义状态类型
interface UserState {
id: number | null;
name: string;
email: string;
isAuthenticated: boolean;
}
// 创建用户Slice
const userSlice = createSlice({
name: 'user',
initialState: {
id: null,
name: '',
email: '',
isAuthenticated: false
} as UserState,
reducers: {
login: (state, action: PayloadAction<UserState>) => {
state.id = action.payload.id;
state.name = action.payload.name;
state.email = action.payload.email;
state.isAuthenticated = true;
},
logout: (state) => {
state.id = null;
state.name = '';
state.email = '';
state.isAuthenticated = false;
}
}
});
// 创建store
const store = configureStore({
reducer: {
user: userSlice.reducer
},
// 添加中间件
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false
})
});
// 导出Actions和类型
export const { login, logout } = userSlice.actions;
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
// 自定义Hooks
export const useUser = () => {
const user = useSelector((state: RootState) => state.user);
const dispatch = useDispatch<AppDispatch>();
const userLogin = useCallback((userData: UserState) => {
dispatch(login(userData));
}, [dispatch]);
const userLogout = useCallback(() => {
dispatch(logout());
}, [dispatch]);
return { user, userLogin, userLogout };
};
1.2 Redux异步Action
tsx
// 创建异步Thunk
const fetchUserProfile = createAsyncThunk(
'user/fetchProfile',
async (userId: number, thunkAPI) => {
try {
const response = await axios.get(`/api/users/${userId}`);
return response.data;
} catch (error) {
return thunkAPI.rejectWithValue(error.response.data);
}
}
);
// 处理异步Action
const userSlice = createSlice({
name: 'user',
initialState: {
profile: null,
loading: false,
error: null
},
extraReducers: (builder) => {
builder
.addCase(fetchUserProfile.pending, (state) => {
state.loading = true;
})
.addCase(fetchUserProfile.fulfilled, (state, action) => {
state.loading = false;
state.profile = action.payload;
})
.addCase(fetchUserProfile.rejected, (state, action) => {
state.loading = false;
state.error = action.payload;
});
}
});
2. MobX响应式状态管理
tsx
import { makeAutoObservable, runInAction } from 'mobx';
import { observer } from 'mobx-react-lite';
// MobX Store
class UserStore {
// 响应式状态
user = {
id: null,
name: '',
email: ''
};
loading = false;
error = null;
constructor() {
// 自动将所有属性转为可观察
makeAutoObservable(this);
}
// 同步Action
setUser(userData) {
this.user = userData;
}
// 异步Action
async fetchUserProfile(userId) {
this.loading = true;
this.error = null;
try {
const response = await axios.get(`/api/users/${userId}`);
runInAction(() => {
this.user = response.data;
this.loading = false;
});
} catch (error) {
runInAction(() => {
this.error = error;
this.loading = false;
});
}
}
// 计算属性
get isAuthenticated() {
return !!this.user.id;
}
}
// 创建实例
const userStore = new UserStore();
// 响应式组件
const UserProfile = observer(() => {
const { user, loading, error, isAuthenticated } = userStore;
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
return (
<div>
{isAuthenticated ? (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
) : (
<LoginPrompt />
)}
</div>
);
});
3. Zustand轻量级状态管理
tsx
import create from 'zustand';
import { persist } from 'zustand/middleware';
// 定义状态类型
interface UserState {
user: {
id: number | null;
name: string;
email: string;
};
token: string | null;
login: (userData: { id: number; name: string; email: string }) => void;
logout: () => void;
fetchProfile: () => Promise<void>;
}
// 创建Store
const useUserStore = create<UserState>(
persist(
(set, get) => ({
user: {
id: null,
name: '',
email: ''
},
token: null,
// 同步登录
login: (userData) => {
set({
user: userData,
token: generateToken(userData)
});
},
// 同步登出
logout: () => {
set({
user: { id: null, name: '', email: '' },
token: null
});
},
// 异步获取用户信息
fetchProfile: async () => {
try {
const response = await axios.get('/api/profile', {
headers: {
Authorization: `Bearer ${get().token}`
}
});
set({ user: response.data });
} catch (error) {
get().logout();
}
}
}),
{
name: 'user-storage', // 本地存储key
getStorage: () => localStorage // 存储引擎
}
)
);
// 组件使用
function UserProfile() {
const { user, login, logout, fetchProfile } = useUserStore();
useEffect(() => {
fetchProfile();
}, []);
return (
<div>
{user.id ? (
<>
<h2>{user.name}</h2>
<button onClick={logout}>退出</button>
</>
) : (
<LoginForm onLogin={login} />
)}
</div>
);
}
4. 状态管理选型建议
Redux适合:
- 大型复杂应用
- 需要详细日志和时间旅行调试
- 多人协作大型项目
MobX适合:
- 中小型项目
- 响应式编程
- 面向对象架构
Zustand适合:
- 轻量级应用
- 快速开发
- 简单状态管理需求
5. 性能与最佳实践
- 选择正确的状态管理库
- 最小化状态粒度
- 使用选择器优化渲染
- 异步处理与错误边界
- 持久化状态
- 代码拆分
6. 状态管理通用模式
tsx
// 通用异步Action模式
async function asyncAction<T>(
action: () => Promise<T>,
onSuccess?: (result: T) => void,
onError?: (error: Error) => void
) {
try {
const result = await action();
onSuccess?.(result);
return result;
} catch (error) {
onError?.(error);
throw error;
}
}
// 使用示例
asyncAction(
() => fetchUserProfile(userId),
(profile) => {
// 成功处理
userStore.setProfile(profile);
},
(error) => {
// 错误处理
toast.error('获取用户信息失败');
}
);
7. 监控与调试
- Redux DevTools
- MobX DevTools
- React DevTools
- Zustand Logger Middleware
总结
状态管理是前端架构的核心,选择合适的库很重要。根据项目复杂度、团队技术栈和性能需求选择最适合的方案。
持续学习、保持开放心态! 🚀🔥
结语:React学习路径推荐
- 掌握基础语法和概念
- 深入理解Hooks
- 实践项目开发
- 学习状态管理(Redux/Mobx/Zustand)
- 性能优化
- 关注生态系统发展
持续学习资源:
- React官方文档
- GitHub开源项目
- 技术博客
- 在线课程平台
加油,成为React大神! 🚀🌟