React 高级阶段学习计划
React 高级阶段学习计划
目标
- 深入理解React的渲染机制和性能优化。
- 学会代码分割和懒加载。
- 掌握单元测试和集成测试。
- 学习TypeScript与React的结合。
学习内容
性能优化
React.memo
- React.memo:用于优化函数组件的性能,避免不必要的重新渲染。
- 示例:
import React, { useState, useMemo } from 'react'; const ExpensiveComponent = React.memo(({ value }) => { console.log('ExpensiveComponent rendered'); // 模拟昂贵的计算 for (let i = 0; i < 1000000000; i++) {} return <div>{value}</div>; }); function App() { const [count, setCount] = useState(0); const [text, setText] = useState(''); const memoizedValue = useMemo(() => { console.log('Computing memoized value'); return count * 2; }, [count]); return ( <div> <h1>Performance Optimization</h1> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment Count</button> <input type="text" value={text} onChange={(e) => setText(e.target.value)} placeholder="Type something" /> <ExpensiveComponent value={memoizedValue} /> </div> ); } export default App;
useCallback和useMemo
- useCallback:用于缓存函数,避免不必要的重新创建。
- useMemo:用于缓存计算结果,避免不必要的计算。
- 示例:
import React, { useState, useCallback, useMemo } from 'react'; function App() { const [count, setCount] = useState(0); const [text, setText] = useState(''); const expensiveComputation = (num) => { console.log('Computing...'); // 模拟昂贵的计算 for (let i = 0; i < 1000000000; i++) {} return num * 2; }; const memoizedValue = useMemo(() => { return expensiveComputation(count); }, [count]); const memoizedCallback = useCallback(() => { console.log('Callback called'); setCount(count + 1); }, [count]); return ( <div> <h1>Performance Optimization</h1> <p>Count: {count}</p> <button onClick={memoizedCallback}>Increment Count</button> <input type="text" value={text} onChange={(e) => setText(e.target.value)} placeholder="Type something" /> <p>Memoized Value: {memoizedValue}</p> </div> ); } export default App;
代码分割与懒加载
React.lazy和Suspense
- React.lazy:用于动态导入组件,实现代码分割。
- Suspense:用于在组件加载时显示加载指示器。
- 示例:
import React, { Suspense, lazy } from 'react'; import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'; const Home = lazy(() => import('./Home')); const About = lazy(() => import('./About')); const Contact = lazy(() => import('./Contact')); function App() { return ( <Router> <div> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li><Link to="/contact">Contact</Link></li> </ul> </nav> <Suspense fallback={<div>Loading...</div>}> <Switch> <Route path="/" exact component={Home} /> <Route path="/about" component={About} /> <Route path="/contact" component={Contact} /> </Switch> </Suspense> </div> </Router> ); } export default App;
测试
单元测试和集成测试
-
Jest:一个JavaScript测试框架。
-
Testing Library:一组用于测试UI组件的库。
-
安装:
npm install --save-dev jest @testing-library/react @testing-library/jest-dom
-
示例:
// Button.js import React from 'react'; function Button({ onClick, label }) { return <button onClick={onClick}>{label}</button>; } export default Button;
// Button.test.js import React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom/extend-expect'; import Button from './Button'; test('renders button with correct label', () => { render(<Button label="Click Me" />); const buttonElement = screen.getByText('Click Me'); expect(buttonElement).toBeInTheDocument(); }); test('calls onClick handler when clicked', () => { const handleClick = jest.fn(); render(<Button label="Click Me" onClick={handleClick} />); const buttonElement = screen.getByText('Click Me'); fireEvent.click(buttonElement); expect(handleClick).toHaveBeenCalled(); });
TypeScript
TypeScript基础
- TypeScript:一种静态类型的编程语言,可以提高代码的可读性和可维护性。
- 安装:
npm install --save typescript @types/react @types/react-dom
- 配置:
- 在项目根目录下创建
tsconfig.json
文件:{ "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": ["src"] }
- 在项目根目录下创建
TypeScript与React结合
-
函数组件:
import React from 'react'; interface ButtonProps { label: string; onClick: () => void; } const Button: React.FC<ButtonProps> = ({ label, onClick }) => { return <button onClick={onClick}>{label}</button>; }; export default Button;
-
类组件:
import React, { Component } from 'react'; interface CounterState { count: number; } class Counter extends Component<{}, CounterState> { state: CounterState = { 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> ); } } export default Counter;
实践项目
个人博客
- 创建项目:
npx create-react-app personal-blog-ts --template typescript cd personal-blog-ts npm start
- 创建组件:
Header.tsx
:头部组件import React from 'react'; const Header: React.FC = () => { return <header><h1>My Personal Blog</h1></header>; }; export default Header;
PostList.tsx
:文章列表组件import React from 'react'; interface Post { id: number; title: string; content: string; } const posts: Post[] = [ { id: 1, title: 'First Post', content: 'This is the first post.' }, { id: 2, title: 'Second Post', content: 'This is the second post.' }, ]; const PostList: React.FC = () => { return ( <div> {posts.map(post => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.content}</p> </div> ))} </div> ); }; export default PostList;
App.tsx
:主组件import React from 'react'; import Header from './Header'; import PostList from './PostList'; const App: React.FC = () => { return ( <div className="App"> <Header /> <PostList /> </div> ); }; export default App;
电子商务网站
- 创建项目:
npx create-react-app ecommerce-ts --template typescript cd ecommerce-ts npm start
- 安装axios:
npm install axios
- 创建组件:
ProductList.tsx
:显示产品列表import React, { useState, useEffect } from 'react'; import axios from 'axios'; interface Product { id: number; title: string; price: number; image: string; } const ProductList: React.FC = () => { const [products, setProducts] = useState<Product[]>([]); useEffect(() => { axios.get<Product[]>('https://fakestoreapi.com/products') .then(response => { setProducts(response.data); }) .catch(error => { console.error('Error fetching products:', error); }); }, []); return ( <div className="product-list"> {products.map(product => ( <div key={product.id} className="product"> <img src={product.image} alt={product.title} /> <h3>{product.title}</h3> <p>${product.price}</p> </div> ))} </div> ); }; export default ProductList;
App.tsx
:主组件import React from 'react'; import ProductList from './ProductList'; const App: React.FC = () => { return ( <div className="App"> <h1>E-commerce Website</h1> <ProductList /> </div> ); }; export default App;
建议
- 定期回顾:每周花时间回顾本周所学内容,确保知识点牢固掌握。
- 参与社区:加入React相关的论坛、Slack群组或Discord服务器,与其他开发者交流心得。
- 阅读源码:尝试阅读一些复杂的React库的源码,提高代码理解和分析能力。
希望这个学习计划能够帮助你系统地学习React高级技能,并通过实践项目巩固所学知识。祝你学习顺利!
你可以将上述Markdown内容复制到任何支持Markdown的编辑器或平台中,以便于查看和使用。