1. React基础语法与TSX实战解析
1.1 TSX核心语法要点
在React开发中,TSX(TypeScript JSX)是日常编码的基础。与普通JSX相比,TSX提供了更严格的类型检查,这能帮助我们在开发阶段就捕获许多潜在错误。
插值表达式的{}使用有几个关键细节:
- 可以放入数组渲染,但数组元素必须是基本类型或JSX元素
- 如果渲染对象数组会直接报错,需要先用
map转换为JSX - 表达式内部不能使用常规语句(如
if),但可以使用三元表达式
javascript复制// 正确示例
const numbers = [1, 2, 3];
return <div>{numbers.map(n => <span key={n}>{n}</span>)}</div>;
// 错误示例
const users = [{name: 'Alice'}, {name: 'Bob'}];
return <div>{users}</div>; // 类型错误!
1.2 事件处理进阶技巧
React事件采用驼峰命名(如onClick),与原生DOM的onclick不同。传参时推荐使用高阶函数模式:
typescript复制const handleClick = (id: number) => (e: React.MouseEvent) => {
console.log(id, e.currentTarget);
};
return (
<button onClick={handleClick(123)}>
点击
</button>
);
重要细节:
- 事件对象是React封装后的
SyntheticEvent,如需原生事件需使用e.nativeEvent - 泛型函数在TSX中必须加逗号:
const fn = <T,>(x: T) => {...},否则会被误认为JSX标签 - 高频触发事件(如
onScroll)建议使用节流/防抖
1.3 属性绑定与样式处理
className的处理有几个实用模式:
javascript复制// 基础用法
<div className="container active"></div>
// 动态类名(推荐clsx或classnames库)
import clsx from 'clsx';
<div className={clsx('base', { active: isActive })}></div>
// 内联样式(对象形式)
<div style={{ color: 'red', fontSize: 16 }}></div>
警告:直接使用
dangerouslySetInnerHTML插入HTML有XSS风险,必须确保内容经过消毒处理
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 现代前端编译工具链
2.1 Babel深度配置
Babel的核心工作流程:
- 解析(Parsing):将代码转换为AST
- 转换(Transforming):插件处理AST
- 生成(Generation):输出目标代码
推荐配置(babel.config.js):
javascript复制module.exports = {
presets: [
['@babel/preset-env', {
targets: '> 0.25%, not dead',
useBuiltIns: 'usage',
corejs: 3
}],
'@babel/preset-react',
'@babel/preset-typescript'
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-transform-runtime'
]
};
2.2 SWC性能优势
SWC(Speedy Web Compiler)的显著特点:
- 编译速度比Babel快20倍以上
- 内置TypeScript支持
- 可以作为Rust库直接嵌入其他工具
webpack集成示例:
javascript复制// webpack.config.js
module: {
rules: [
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'swc-loader',
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true
}
}
}
}
}
]
}
3. React核心渲染机制
3.1 虚拟DOM原理
虚拟DOM(Virtual DOM)的本质是一个JS对象树,它:
- 轻量:仅包含必要属性
- 快速:在内存中操作,避免直接DOM操作
- 差异更新:通过diff算法最小化DOM操作
mermaid复制graph TD
A[State Change] --> B[New Virtual DOM]
B --> C[Diff Algorithm]
D[Previous Virtual DOM] --> C
C --> E[DOM Updates]
3.2 Fiber架构解析
Fiber的核心改进:
- 增量渲染:将渲染工作拆分为多个小任务
- 任务优先级:区分高优先级(如动画)和低优先级更新
- 恢复能力:可以中断和恢复渲染过程
关键数据结构:
typescript复制interface FiberNode {
tag: WorkTag;
key: null | string;
elementType: any;
type: any;
stateNode: any;
return: FiberNode | null;
child: FiberNode | null;
sibling: FiberNode | null;
index: number;
ref: any;
pendingProps: any;
memoizedProps: any;
memoizedState: any;
// ...其他属性
}
4. 状态管理深度指南
4.1 useState高级用法
数组状态的最佳实践:
typescript复制const [todos, setTodos] = useState<Todo[]>([]);
// 添加
setTodos(prev => [...prev, newTodo]);
// 删除
setTodos(prev => prev.filter(t => t.id !== id));
// 更新
setTodos(prev => prev.map(t =>
t.id === id ? { ...t, completed: true } : t
));
// 排序
setTodos(prev => [...prev].sort((a, b) => a.priority - b.priority));
对象状态更新模式:
typescript复制const [user, setUser] = useState<User>({ name: '', age: 0 });
// 单字段更新
setUser(prev => ({ ...prev, name: 'Alice' }));
// 多字段更新
setUser(prev => ({
...prev,
name: 'Bob',
age: 25
}));
4.2 useReducer复杂状态管理
适合场景:
- 状态逻辑复杂
- 包含多个子值
- 下一个状态依赖前一个状态
购物车示例:
typescript复制const cartReducer = (state: CartState, action: CartAction) => {
switch (action.type) {
case 'ADD_ITEM':
return {
...state,
items: [...state.items, action.payload],
total: state.total + action.payload.price
};
case 'REMOVE_ITEM':
return {
...state,
items: state.items.filter(item => item.id !== action.payload.id),
total: state.total - action.payload.price
};
default:
return state;
}
};
const [cart, dispatch] = useReducer(cartReducer, initialState);
4.3 useImmer简化不可变更新
安装:npm install immer use-immer
typescript复制import { useImmer } from 'use-immer';
const [todos, updateTodos] = useImmer([
{ id: 1, text: 'Learn React', done: false }
]);
// 直接修改draft
updateTodos(draft => {
draft.push({ id: 2, text: 'Try Immer', done: false });
draft[0].done = true;
});
5. 高级Hooks应用
5.1 useSyncExternalStore外部状态集成
浏览器API集成示例:
typescript复制function useOnlineStatus() {
const isOnline = useSyncExternalStore(
subscribe, // 订阅函数
() => navigator.onLine, // 客户端获取快照
() => true // SSR默认值
);
return isOnline;
}
function subscribe(callback: () => void) {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
}
5.2 自定义Hook设计
封装数据请求Hook:
typescript复制function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const response = await fetch(url);
const result = await response.json();
setData(result);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
}
6. 性能优化策略
6.1 React.memo与useMemo
组件记忆化:
typescript复制const ExpensiveComponent = React.memo(
({ list }: { list: Item[] }) => {
// 组件逻辑
},
(prevProps, nextProps) => {
// 自定义比较函数
return prevProps.list.length === nextProps.list.length;
}
);
值记忆化:
typescript复制const sortedList = useMemo(() => {
return [...list].sort((a, b) => a.value - b.value);
}, [list]);
6.2 useCallback避免重复渲染
typescript复制const handleClick = useCallback(() => {
// 事件处理逻辑
}, [dependencies]);
6.3 虚拟列表优化长列表
使用react-window示例:
typescript复制import { FixedSizeList as List } from 'react-window';
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
const App = () => (
<List
height={600}
itemCount={1000}
itemSize={35}
width={300}
>
{Row}
</List>
);
7. 常见问题排查
7.1 状态更新未触发渲染
可能原因:
- 直接修改了状态对象(如
obj.key = value) - 使用了相同的引用(如
setArr(arr.sort())) - 在class组件中错误使用
this.state=直接赋值
解决方案:
- 始终使用不可变更新
- 对于复杂对象,使用解构或immer
- 检查React DevTools中的状态变化
7.2 内存泄漏警告
常见场景:
- 未清理的订阅
- 未取消的异步请求
- 未清除的定时器
正确做法:
typescript复制useEffect(() => {
const controller = new AbortController();
const fetchData = async () => {
try {
const res = await fetch(url, {
signal: controller.signal
});
// 处理结果
} catch (err) {
if (err.name !== 'AbortError') {
// 处理真实错误
}
}
};
fetchData();
return () => {
controller.abort();
};
}, [url]);
7.3 组件重复渲染问题
排查步骤:
- 使用React DevTools的Profiler工具记录渲染
- 检查props是否频繁变化
- 确认useMemo/useCallback依赖项正确
- 避免在渲染函数中创建新对象/函数
优化技巧:
typescript复制// 不推荐(每次渲染创建新对象)
<Child style={{ color: 'red' }} />
// 推荐(对象记忆化)
const childStyle = useMemo(() => ({ color: 'red' }), []);
<Child style={childStyle} />
8. TypeScript高级模式
8.1 类型安全的事件处理
typescript复制type ButtonProps = {
onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
};
const Button = ({ onClick }: ButtonProps) => (
<button onClick={onClick}>Click</button>
);
8.2 泛型组件设计
typescript复制interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
function List<T>({ items, renderItem }: ListProps<T>) {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{renderItem(item)}</li>
))}
</ul>
);
}
// 使用
<List<{ id: number; name: string }>
items={users}
renderItem={user => <span>{user.name}</span>}
/>
8.3 as const断言
typescript复制// 普通数组 → 类型为 (number | string)[]
const mixed = [1, 'text'];
// as const → 类型为 readonly [1, "text"]
const tuple = [1, 'text'] as const;
9. 测试策略
9.1 单元测试(Jest)
typescript复制import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('increments count', () => {
render(<Counter />);
const button = screen.getByText('Increment');
fireEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
9.2 组件测试(React Testing Library)
typescript复制test('loads and displays greeting', async () => {
render(<Fetch url="/greeting" />);
fireEvent.click(screen.getByText('Load Greeting'));
await screen.findByRole('heading');
expect(screen.getByRole('heading')).toHaveTextContent('Hello');
expect(screen.getByRole('button')).toBeDisabled();
});
9.3 E2E测试(Cypress)
typescript复制describe('Todo App', () => {
it('adds new todo', () => {
cy.visit('/');
cy.get('input').type('Learn Cypress{enter}');
cy.contains('Learn Cypress').should('exist');
});
});
10. 项目结构最佳实践
推荐结构:
code复制src/
├── components/
│ ├── common/ # 通用UI组件
│ ├── features/ # 业务组件
│ └── layouts/ # 布局组件
├── hooks/ # 自定义hooks
├── stores/ # 状态管理
├── services/ # API服务
├── utils/ # 工具函数
├── types/ # 类型定义
├── assets/ # 静态资源
├── pages/ # 页面组件
└── App.tsx # 根组件
配置路径别名(tsconfig.json):
json复制{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["src/components/*"],
"@hooks/*": ["src/hooks/*"]
}
}
}
11. 样式方案选型
11.1 CSS Modules
css复制/* styles.module.css */
.container {
padding: 1rem;
}
.active {
background: blue;
}
typescript复制import styles from './styles.module.css';
const Component = () => (
<div className={styles.container}>
<button className={styles.active}>Submit</button>
</div>
);
11.2 CSS-in-JS(Emotion)
typescript复制/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
const style = css`
padding: 1rem;
background: ${isActive ? 'blue' : 'gray'};
`;
const Component = () => (
<div css={style}>
Dynamic Styles
</div>
);
11.3 Tailwind CSS
typescript复制const Component = () => (
<div className="p-4 bg-blue-500 hover:bg-blue-700">
<button className="px-4 py-2 rounded">
Click Me
</button>
</div>
);
12. 服务端渲染(Next.js)
12.1 基础页面
typescript复制// pages/index.tsx
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return { props: { data } };
}
export default function Home({ data }: { data: any }) {
return (
<div>
<h1>Server-Side Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
12.2 静态生成
typescript复制// pages/posts/[id].tsx
export async function getStaticPaths() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
const paths = posts.map(post => ({
params: { id: post.id.toString() }
}));
return { paths, fallback: false };
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://api.example.com/posts/${params.id}`);
const post = await res.json();
return { props: { post } };
}
13. 状态管理进阶
13.1 Context API模式
typescript复制const ThemeContext = React.createContext({
theme: 'light',
toggleTheme: () => {},
});
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = useCallback(() => {
setTheme(prev => prev === 'light' ? 'dark' : 'light');
}, []);
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
function useTheme() {
return useContext(ThemeContext);
}
13.2 Zustand轻量状态
typescript复制import create from 'zustand';
interface StoreState {
count: number;
increment: () => void;
decrement: () => void;
}
const useStore = create<StoreState>(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
decrement: () => set(state => ({ count: state.count - 1 })),
}));
function Counter() {
const { count, increment } = useStore();
return <button onClick={increment}>{count}</button>;
}
14. 动画实现方案
14.1 CSS Transition
typescript复制const [isOpen, setIsOpen] = useState(false);
return (
<div
style={{
transition: 'all 0.3s ease',
opacity: isOpen ? 1 : 0,
height: isOpen ? 'auto' : 0
}}
>
Content
</div>
);
14.2 Framer Motion
typescript复制import { motion } from 'framer-motion';
const variants = {
open: { opacity: 1, x: 0 },
closed: { opacity: 0, x: "-100%" },
};
function Toggle() {
const [isOpen, setIsOpen] = useState(false);
return (
<motion.div
animate={isOpen ? "open" : "closed"}
variants={variants}
>
<button onClick={() => setIsOpen(!isOpen)}>
Toggle
</button>
</motion.div>
);
}
15. 性能监控与分析
15.1 React Profiler
typescript复制import { Profiler } from 'react';
function onRender(
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime,
interactions
) {
console.log({
id,
phase,
actualDuration,
baseDuration
});
}
function App() {
return (
<Profiler id="Navigation" onRender={onRender}>
<Navigation />
</Profiler>
);
}
15.2 Lighthouse审计
关键指标:
- First Contentful Paint (FCP)
- Largest Contentful Paint (LCP)
- Cumulative Layout Shift (CLS)
- Total Blocking Time (TBT)
优化建议:
- 代码分割(React.lazy + Suspense)
- 图片懒加载
- 字体预加载
- 关键CSS内联
16. 移动端适配策略
16.1 响应式布局
css复制/* 移动优先 */
.container {
padding: 1rem;
}
/* 平板 */
@media (min-width: 768px) {
.container {
padding: 2rem;
}
}
/* 桌面 */
@media (min-width: 1024px) {
.container {
max-width: 1200px;
margin: 0 auto;
}
}
16.2 触摸优化
typescript复制function Swipeable({ onSwipeLeft, onSwipeRight }) {
const [startX, setStartX] = useState(null);
const handleTouchStart = (e) => {
setStartX(e.touches[0].clientX);
};
const handleTouchEnd = (e) => {
if (!startX) return;
const endX = e.changedTouches[0].clientX;
const diff = startX - endX;
if (diff > 50) onSwipeLeft();
if (diff < -50) onSwipeRight();
setStartX(null);
};
return (
<div
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
>
Swipe me
</div>
);
}
17. 国际化方案
17.1 react-i18next配置
typescript复制import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n.use(initReactI18next).init({
resources: {
en: {
translation: {
welcome: 'Welcome'
}
},
zh: {
translation: {
welcome: '欢迎'
}
}
},
lng: 'en',
fallbackLng: 'en'
});
function App() {
const { t } = useTranslation();
return <h1>{t('welcome')}</h1>;
}
17.2 动态语言切换
typescript复制function LanguageSwitcher() {
const { i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
return (
<div>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('zh')}>中文</button>
</div>
);
}
18. 表单处理方案
18.1 React Hook Form
typescript复制import { useForm } from 'react-hook-form';
type FormData = {
username: string;
email: string;
};
function Form() {
const { register, handleSubmit, formState: { errors } } = useForm<FormData>();
const onSubmit = (data: FormData) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register('username', { required: true })}
placeholder="Username"
/>
{errors.username && <span>Required</span>}
<input
{...register('email', {
required: true,
pattern: /^\S+@\S+$/i
})}
placeholder="Email"
/>
{errors.email && <span>Invalid email</span>}
<button type="submit">Submit</button>
</form>
);
}
18.2 Formik复杂表单
typescript复制import { Formik, Field, Form } from 'formik';
function SignupForm() {
return (
<Formik
initialValues={{ email: '', password: '' }}
onSubmit={(values) => {
console.log(values);
}}
>
<Form>
<Field name="email" type="email" />
<Field name="password" type="password" />
<button type="submit">Submit</button>
</Form>
</Formik>
);
}
19. 数据获取模式
19.1 SWR缓存策略
typescript复制import useSWR from 'swr';
const fetcher = (url: string) => fetch(url).then(res => res.json());
function Profile() {
const { data, error } = useSWR('/api/user', fetcher, {
refreshInterval: 3000,
revalidateOnFocus: false
});
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return <div>Hello {data.name}!</div>;
}
19.2 React Query高级用法
typescript复制import { useQuery, useMutation, QueryClient } from 'react-query';
const queryClient = new QueryClient();
function Todos() {
const { data } = useQuery('todos', () =>
fetch('/api/todos').then(res => res.json())
);
const mutation = useMutation(
(newTodo) => fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(newTodo)
}),
{
onSuccess: () => {
queryClient.invalidateQueries('todos');
}
}
);
return (
<div>
{data?.map(todo => (
<div key={todo.id}>{todo.text}</div>
))}
<button
onClick={() => {
mutation.mutate({ text: 'New Todo' });
}}
>
Add Todo
</button>
</div>
);
}
20. 项目部署与CI/CD
20.1 Docker容器化
dockerfile复制# Dockerfile
FROM node:16-alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
20.2 GitHub Actions自动化
yaml复制# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v2
with:
name: build
path: build
21. 微前端架构
21.1 Module Federation配置
javascript复制// webpack.config.js
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button'
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true }
}
})
]
};
21.2 动态加载远程组件
typescript复制const RemoteButton = React.lazy(() =>
import('app1/Button').catch(() =>
import('./FallbackButton')
)
);
function App() {
return (
<React.Suspense fallback="Loading...">
<RemoteButton />
</React.Suspense>
);
}
22. Web Workers优化
22.1 复杂计算卸载
typescript复制// worker.js
self.onmessage = (e) => {
const result = heavyCalculation(e.data);
self.postMessage(result);
};
// main.js
const worker = new Worker('./worker.js');
function App() {
const [result, setResult] = useState(null);
const handleClick = () => {
worker.postMessage(inputData);
worker.onmessage = (e) => setResult(e.data);
};
return (
<div>
<button onClick={handleClick}>Calculate</button>
{result && <div>{result}</div>}
</div>
);
}
22.2 Comlink简化通信
typescript复制// worker.ts
import { expose } from 'comlink';
const api = {
calculate(data) {
return heavyCalculation(data);
}
};
expose(api);
// main.ts
import { wrap } from 'comlink';
async function init() {
const worker = new Worker('./worker.ts');
const workerApi = wrap<typeof import('./worker').api>(worker);
const result = await workerApi.calculate(data);
console.log(result);
}
23. 错误边界与监控
23.1 React错误边界
typescript复制class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
logErrorToService(error, info.componentStack);
}
render() {
if (this.state.hasError) {
return <FallbackUI />;
}
return this.props.children;
}
}
function App() {
return (
<ErrorBoundary>
<UnstableComponent />
</ErrorBoundary>
);
}
23.2 Sentry监控集成
typescript复制import * as Sentry from '@sentry/react';
import { Integrations } from '@sentry/tracing';
Sentry.init({
dsn: 'YOUR_DSN',
integrations: [new Integrations.BrowserTracing()],
tracesSampleRate: 1.0,
});
function App() {
return (
<Sentry.ErrorBoundary fallback={<p>An error occurred</p>}>
<YourApp />
</Sentry.ErrorBoundary>
);
}
24. 无障碍(a11y)实践
24.1 ARIA属性使用
typescript复制function Toggle() {
const [isOpen, setIsOpen] = useState(false);
return (
<div
role="button"
tabIndex={0}
aria-expanded={isOpen}
onClick={() => setIsOpen(!isOpen)}
onKeyDown={(e) => e.key === 'Enter' && setIsOpen(!isOpen)}
>
{isOpen ? 'Collapse' : 'Expand'}
</div>
);
}
24.2 键盘导航支持
typescript复制function Menu() {
const items = ['Home', 'About', 'Contact'];
const [activeIndex, setActiveIndex] = useState(0);
const handleKeyDown = (e) => {
if (e.key === 'ArrowDown') {
setActiveIndex(prev => Math.min(prev + 1, items.length - 1));
} else if (e.key === 'ArrowUp') {
setActiveIndex(prev => Math.max(prev - 1, 0));
} else if (e.key === 'Enter') {
// 处理选中
}
};
return (
<ul role="menu" onKeyDown={handleKeyDown}>
{items.map((item, index) => (
<li
key={item}
role="menuitem"
tabIndex={0}
aria-selected={index === activeIndex}
>
{item}
</li>
))}
</ul>
);
}
25. 未来趋势探索
25.1 React Server Components
typescript复制// Note.server.js
import db from 'db.server';
export default function Note({ id }) {
const note = db.notes.get(id);
return (
<div>
<h1>{note.title}</h1>
<p>{note.content}</p>
</div>
);
}
// ClientComponent.client.js
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
25.2 React并发模式
typescript复制function App() {
const [resource, setResource] = useState(fetchProfileData());
return (
<Suspense fallback={<h1>Loading profile...</h1>}>
<ProfileDetails resource={resource} />
<Suspense fallback={<h1>Loading posts...</h1>}>
<ProfileTimeline resource={resource} />
</Suspense>
</Suspense>
);
}
26. 开发者工具推荐
26.1 必备Chrome扩展
- React Developer Tools
- Redux DevTools
- Apollo Client DevTools
- JSON Formatter
- Lighthouse
26.2 VS Code插件
- ESLint
- Prettier
- GraphQL
- Tailwind CSS IntelliSense
- Path IntelliSense
26.3 实用在线工具
- CodeSandbox
- Figma
- Postman
- Can I use
- BundlePhobia
27. 学习资源推荐
27.1 官方文档
27.2 进阶教程
- Epic React (Kent C. Dodds)
- Advanced React Patterns (Frontend Masters)
- Fullstack Open (University of Helsinki)
27.3 社区资源
- Reactiflux Discord
- DEV.to React社区
- Stack Overflow
- GitHub开源项目
28. 项目实战建议
28.1 个人项目创意
- 个人博客系统
- 任务管理工具
- 实时协作白板
- 数据可视化仪表盘
- 电商网站前端
28.2 开源贡献指南
- 从文档改进开始
- 寻找"good first issue"标签
- 克隆项目并运行示例
- 遵循项目贡献规范
- 编写清晰的PR描述
28.3 技术博客写作
- 记录问题解决过程
- 分享项目架构决策
- 对比技术方案优劣
- 制作可交互示例
- 参与社区讨论
29. 职业发展建议
29.1 技术路线规划
- 初级:掌握核心概念与生态工具
- 中级:深入性能优化与架构设计
- 高级:引领技术创新与团队成长
29.2 面试准备重点
- 核心概念(虚拟DOM、Hooks原理)
- 性能优化策略
- 状态管理方案对比
- 项目架构设计
- 实际编码能力
29.3 持续学习策略
- 每周阅读源码
- 每月尝试新技术
- 季度项目复盘
- 年度技术规划
- 参与技术社区
30. 个人经验分享
在实际React开发中,有几个关键点我深有体会:
类型安全优先:从项目开始就使用TypeScript,虽然初期配置稍复杂,但长期来看能显著减少运行时错误。建议开启
