React 进阶阶段学习计划
目标
- 掌握自定义Hooks的创建和使用。
- 深入理解上下文(Context)和Redux的高级用法。
- 学会服务端渲染(SSR)。
- 深入探讨性能优化技巧。
学习内容
自定义Hooks
创建和使用自定义Hooks
-
自定义Hooks:用于提取组件逻辑,使代码更加模块化和复用。
-
示例:
jsx// useFetch.js import { useState, useEffect } from 'react'; function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { async function fetchData() { try { const response = await fetch(url); const json = await response.json(); setData(json); } catch (err) { setError(err); } finally { setLoading(false); } } fetchData(); }, [url]); return { data, loading, error }; } export default useFetch;
jsx// App.js import React from 'react'; import useFetch from './useFetch'; function App() { const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts'); if (loading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> <h1>Data from API</h1> <ul> {data.map(item => ( <li key={item.id}>{item.title}</li> ))} </ul> </div> ); } export default App;
上下文(Context)和Redux的高级用法
上下文(Context)的高级用法
-
Context Consumer:用于在函数组件中消费Context。
-
示例 :
jsx// ThemeContext.js import React, { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); // 提供者组件 function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); const toggleTheme = () => { setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light')); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); } // 消费者组件 function ThemedButton() { const { theme, toggleTheme } = useContext(ThemeContext); return ( <button onClick={toggleTheme} style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}> Toggle Theme </button> ); } // App.js import React from 'react'; import ThemeProvider from './ThemeProvider'; import ThemedButton from './ThemedButton'; function App() { return ( <ThemeProvider> <ThemedButton /> </ThemeProvider> ); } export default App;
Redux的高级用法
-
Redux Toolkit:简化Redux的开发流程。
-
安装:
bashnpm install @reduxjs/toolkit react-redux
-
示例:
jsx// store.js import { configureStore, createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; }, }, }); const store = configureStore({ reducer: { counter: counterSlice.reducer, }, }); export const { increment, decrement } = counterSlice.actions; export default store;
jsx// App.js import React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { increment, decrement } from './store'; import { Provider } from 'react-redux'; import store from './store'; function Counter() { const count = useSelector((state) => state.counter.value); const dispatch = useDispatch(); return ( <div> <p>Count: {count}</p> <button onClick={() => dispatch(increment())}>Increment</button> <button onClick={() => dispatch(decrement())}>Decrement</button> </div> ); } function App() { return ( <Provider store={store}> <Counter /> </Provider> ); } export default App;
服务端渲染(SSR)
Next.js
-
Next.js:一个流行的React框架,支持服务端渲染。
-
安装:
bashnpx create-next-app@latest my-app cd my-app npm run dev
-
示例:
jsx// pages/index.js import { useState } from 'react'; export default function Home() { const [count, setCount] = useState(0); return ( <div> <h1>Welcome to Next.js!</h1> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
jsx// pages/api/hello.js export default function handler(req, res) { res.status(200).json({ name: 'John Doe' }); }
性能优化的深入探讨
使用React Profiler
-
React Profiler:用于分析组件的渲染性能。
-
启用Profiler :
jsximport React, { Profiler } from 'react'; function onRender(id, phase, actualDuration, baseDuration, startTime, commitTime) { console.log({ id, phase, actualDuration, baseDuration, startTime, commitTime }); } function App() { return ( <Profiler id="App" onRender={onRender}> <div> <h1>React Profiler Example</h1> {/* 其他组件 */} </div> </Profiler> ); } export default App;
使用React.memo和PureComponent
-
React.memo:用于优化函数组件的性能。
-
PureComponent:用于优化类组件的性能。
-
示例:
jsx// MyComponent.js import React, { PureComponent } from 'react'; class MyComponent extends PureComponent { render() { return <div>{this.props.value}</div>; } } export default MyComponent;
jsx// MyFunctionComponent.js import React from 'react'; const MyFunctionComponent = React.memo(({ value }) => { return <div>{value}</div>; }); export default MyFunctionComponent;
实践项目
社交媒体应用
-
创建项目 :
bashnpx create-next-app@latest social-media-app cd social-media-app npm run dev
-
创建组件 :
-
PostList.js
:显示帖子列表jsximport React, { useState, useEffect } from 'react'; import axios from 'axios'; function PostList() { const [posts, setPosts] = useState([]); useEffect(() => { axios.get('https://jsonplaceholder.typicode.com/posts') .then(response => { setPosts(response.data); }) .catch(error => { console.error('Error fetching posts:', error); }); }, []); return ( <div className="post-list"> {posts.map(post => ( <div key={post.id} className="post"> <h3>{post.title}</h3> <p>{post.body}</p> </div> ))} </div> ); } export default PostList;
-
App.js
:主组件jsximport React from 'react'; import PostList from '../components/PostList'; function Home() { return ( <div className="container"> <h1>Social Media App</h1> <PostList /> </div> ); } export default Home;
-
博客管理系统
-
创建项目 :
bashnpx create-react-app blog-management --template typescript cd blog-management npm start
-
安装axios :
bashnpm install axios
-
创建组件 :
-
PostForm.tsx
:添加和编辑帖子的表单tsximport React, { useState } from 'react'; import axios from 'axios'; interface Post { id?: number; title: string; content: string; } interface PostFormProps { initialPost?: Post; onSubmit: (post: Post) => void; } const PostForm: React.FC<PostFormProps> = ({ initialPost, onSubmit }) => { const [post, setPost] = useState<Post>({ id: initialPost?.id, title: initialPost?.title || '', content: initialPost?.content || '', }); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); onSubmit(post); setPost({ title: '', content: '' }); }; return ( <form onSubmit={handleSubmit}> <input type="text" value={post.title} onChange={(e) => setPost({ ...post, title: e.target.value })} placeholder="Title" /> <textarea value={post.content} onChange={(e) => setPost({ ...post, content: e.target.value })} placeholder="Content" /> <button type="submit">Submit</button> </form> ); }; export default PostForm;
-
PostList.tsx
:显示帖子列表tsximport React, { useState, useEffect } from 'react'; import axios from 'axios'; import PostForm from './PostForm'; interface Post { id: number; title: string; content: string; } const PostList: React.FC = () => { const [posts, setPosts] = useState<Post[]>([]); const [editingPost, setEditingPost] = useState<Post | null>(null); useEffect(() => { axios.get<Post[]>('https://jsonplaceholder.typicode.com/posts') .then(response => { setPosts(response.data.slice(0, 10)); }) .catch(error => { console.error('Error fetching posts:', error); }); }, []); const handleEdit = (post: Post) => { setEditingPost(post); }; const handleDelete = (postId: number) => { setPosts(posts.filter(post => post.id !== postId)); }; const handleSave = (post: Post) => { if (post.id) { setPosts(posts.map(p => (p.id === post.id ? post : p))); } else { setPosts([...posts, post]); } setEditingPost(null); }; return ( <div className="post-list"> {editingPost ? ( <PostForm initialPost={editingPost} onSubmit={handleSave} /> ) : ( <PostForm onSubmit={handleSave} /> )} <ul> {posts.map(post => ( <li key={post.id}> <h3>{post.title}</h3> <p>{post.content}</p> <button onClick={() => handleEdit(post)}>Edit</button> <button onClick={() => handleDelete(post.id)}>Delete</button> </li> ))} </ul> </div> ); }; export default PostList;
-
App.tsx
:主组件tsximport React from 'react'; import PostList from './components/PostList'; const App: React.FC = () => { return ( <div className="App"> <h1>Blog Management System</h1> <PostList /> </div> ); }; export default App;
-
建议
- 定期回顾:每周花时间回顾本周所学内容,确保知识点牢固掌握。
- 参与社区:加入React相关的论坛、Slack群组或Discord服务器,与其他开发者交流心得。
- 阅读源码:尝试阅读一些复杂的React库的源码,提高代码理解和分析能力。
希望这个学习计划能够帮助你系统地学习React进阶技能,并通过实践项目巩固所学知识。祝你学习顺利!
你可以将上述Markdown内容复制到任何支持Markdown的编辑器或平台中,以便于查看和使用。