大家好,我是小杨。今天不聊具体的技术实现,想和大家分享我这几年使用React全家桶的一些心得体会。记得刚入门时,总觉得React生态圈太庞大,不知道从何学起。现在回头看,其实每个工具的出现都是为了解决特定的问题。
一、什么是React全家桶?
在我理解中,React全家桶不仅仅是指官方的那些库,更是一个完整的开发生态。主要包括:
jsx
// 典型的全家桶项目结构
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import axios from 'axios';
// 状态管理
const store = configureStore({
reducer: {
user: userReducer,
posts: postsReducer
}
});
function App() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Header />
<MainContent />
<Footer />
</div>
</Router>
</Provider>
);
}
二、路由管理:React Router的进化
还记得最早的时候,我们还在用各种hash路由,现在React Router已经发展到v6版本了。
jsx
// 以前的路由配置
import { Switch, Route } from 'react-router-dom';
function OldRouter() {
return (
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
);
}
// 现在的v6版本
import { Routes, Route } from 'react-router-dom';
function NewRouter() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<UserProfile />} />
</Routes>
);
}
v6版本最大的改进是更好的TypeScript支持和更简洁的API设计。
三、状态管理:从Redux到Zustand
状态管理是React应用的核心,我经历了从Redux到各种轻量级方案的演变。
jsx
// 传统的Redux写法
const initialState = {
loading: false,
data: null,
error: null
};
function userReducer(state = initialState, action) {
switch (action.type) {
case 'FETCH_START':
return { ...state, loading: true };
case 'FETCH_SUCCESS':
return { ...state, loading: false, data: action.payload };
case 'FETCH_ERROR':
return { ...state, loading: false, error: action.payload };
default:
return state;
}
}
// 现在更喜欢的Zustand写法
import create from 'zustand';
const useUserStore = create((set) => ({
user: null,
loading: false,
fetchUser: async (userId) => {
set({ loading: true });
try {
const response = await axios.get(`/api/users/${userId}`);
set({ user: response.data, loading: false });
} catch (error) {
set({ error: error.message, loading: false });
}
}
}));
四、数据获取:从componentDidMount到React Query
数据获取的演进是我觉得最有意思的部分。
jsx
// 类组件时代
class UserList extends React.Component {
state = {
users: [],
loading: false
};
async componentDidMount() {
this.setState({ loading: true });
try {
const response = await axios.get('/api/users');
this.setState({ users: response.data, loading: false });
} catch (error) {
this.setState({ error: error.message, loading: false });
}
}
render() {
// 渲染逻辑
}
}
// Hook时代
import { useQuery } from 'react-query';
function UserList() {
const { data: users, isLoading, error } = useQuery('users', () =>
axios.get('/api/users').then(res => res.data)
);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
{users.map(user => (
<UserItem key={user.id} user={user} />
))}
</div>
);
}
五、样式方案:从CSS到CSS-in-JS
样式方案的选择也反映着React生态的发展。
jsx
// 传统的CSS Modules
import styles from './Button.module.css';
function Button({ children }) {
return <button className={styles.primary}>{children}</button>;
}
// Styled Components
import styled from 'styled-components';
const StyledButton = styled.button`
background: ${props => props.primary ? '#007bff' : '#6c757d'};
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
&:hover {
opacity: 0.8;
}
`;
function ModernButton({ primary, children }) {
return <StyledButton primary={primary}>{children}</StyledButton>;
}
六、构建工具:从Webpack到Vite
构建工具的演进大大提升了开发体验。
jsx
// 以前的webpack配置复杂到需要专门维护
module.exports = {
// 一大堆配置...
};
// 现在的Vite几乎零配置
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 3000
}
});
七、我的技术选型建议
基于这些年的经验,我总结了一些选型原则:
- 新手项目:Create React App + React Router + Context API
- 中型项目:Vite + React Router + Zustand + React Query
- 大型项目:Next.js + Redux Toolkit + TypeScript
八、实战技巧分享
分享几个我在项目中总结的小技巧:
jsx
// 1. 自定义Hook封装数据逻辑
function useApi(endpoint) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get(endpoint);
setData(response.data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchData();
}, [endpoint]);
return { data, loading, error };
}
// 2. 组件组合模式
function Card({ header, body, footer }) {
return (
<div className="card">
{header && <div className="card-header">{header}</div>}
<div className="card-body">{body}</div>
{footer && <div className="card-footer">{footer}</div>}
</div>
);
}
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!