2月阅读周·React设计模式与最佳实践:React 基础与设计模式篇
引言
《React设计模式与最佳实践》本书将带你全面了解React中最有价值的设计模式,并展示如何在全新或已有的真实项目中应用设计模式与最佳实践。本书将帮助你让应用变得更加灵活、运行更流畅并且更容易维护——在不降低质量的情况下极大地提升工作流的速度。
本书包括以下几部分内容:
- React的内部原理。
- 编写整洁且可维护的代码,即保持代码整洁并遵循编程风格指南。
- 开发能够在整个应用中复用的组件,构建应用的一个关键因素在于使用组件,而要想保持代码库整洁且可维护,最重要的是开发真正可复用的组件。
- 搭建应用架构,并创建真正可用的表单。
- 服务端渲染是,虽然该特性开箱即用,但学习其正确用法很重要,因为这样才能充分加以利用。
- 提升应用性能,性能是Web平台吸引用户的重要因素之一。React提供了一系列工具和技术来创建快如闪电的应用,这一章将全面介绍这些内容。
- 测试与调试,编写全面的测试集对于创建稳定且可维护的代码至关重要。从另一方面来看,bug总会出现,而知道如何调试并尽早发现问题很关键。
React 基础与设计模式
React 基础回顾
React 的核心思想
React 的核心思想是通过组件化构建用户界面。每个组件都是一个独立的单元,负责自己的渲染逻辑和状态管理。React 的声明式编程模型使得开发者可以更专注于描述 UI 应该是什么样子,而不是如何实现。
组件化开发的优势
- 可复用性:组件可以在多个地方重复使用。
- 可维护性:每个组件的逻辑独立,便于调试和维护。
- 可测试性:独立的组件更容易进行单元测试。
React 设计模式
容器组件与展示组件模式
容器组件负责管理数据和业务逻辑,展示组件负责渲染 UI。这种模式有助于分离关注点,使代码更清晰。
示例代码:容器组件与展示组件
// 展示组件
function UserList({ users }) {
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
// 容器组件
function UserListContainer() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('/api/users')
.then(response => response.json())
.then(data => setUsers(data));
}, []);
return <UserList users={users} />;
}
高阶组件(HOC)模式
高阶组件是一个函数,接收一个组件并返回一个新的组件。HOC 通常用于复用逻辑,如数据获取、权限控制等。
示例代码:高阶组件
function withLoading(WrappedComponent) {
return function WithLoadingComponent({ isLoading, ...props }) {
if (isLoading) {
return <div>Loading...</div>;
}
return <WrappedComponent {...props} />;
};
}
const UserListWithLoading = withLoading(UserList);
Render Props 模式
Render Props 是一种通过 prop 传递渲染逻辑的模式。它允许组件共享代码,同时保持灵活性。
示例代码:Render Props
function DataFetcher({ url, render }) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => setData(data));
}, [url]);
return render(data);
}
function App() {
return (
<DataFetcher
url="/api/users"
render={data => (data ? <UserList users={data} /> : <div>Loading...</div>)}
/>
);
}
状态管理
组件内部状态
对于简单的状态管理,可以使用 useState
Hook 或类组件的 this.state
。
示例代码:使用 useState
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
全局状态管理
对于复杂的应用,可以使用 Context API 或状态管理库(如 Redux)来管理全局状态。
示例代码:使用 Context API
const UserContext = React.createContext();
function UserProvider({ children }) {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
}
function UserProfile() {
const { user } = useContext(UserContext);
return (
<div>
{user ? <p>Welcome, {user.name}!</p> : <p>Please log in.</p>}
</div>
);
}
代码说明:
serProvider
组件是一个上下文提供者(Context Provider)。这个组件的主要作用是管理用户状态,通过 UserContext
将这个状态提供给其所有子组件,使得子组件可以共享和更新这个用户状态:
const [user, setUser] = useState(null);
:
- 这行代码使用了 React 的
useState
钩子来创建一个名为user
的状态变量,并将其初始值设置为null
。 setUser
是一个函数,用于更新user
状态的值。
return <UserContext.Provider value={{ user, setUser }}>{children}</UserContext.Provider>;
:
- 这行代码返回了一个
UserContext.Provider
组件,它是UserContext
的提供者。 value
属性是一个对象,包含了user
状态和setUser
函数。这样,所有嵌套在UserProvider
组件中的子组件都可以通过useContext(UserContext)
来访问这些值。{children}
表示UserProvider
组件的子组件,这些子组件将能够访问UserContext
提供的值。
性能优化
避免不必要的渲染
使用 React.memo
或 shouldComponentUpdate
避免不必要的渲染。
示例代码:使用 React.memo
const MemoizedUserList = React.memo(UserList);
使用 useCallback
和 useMemo
useCallback
和 useMemo
可以缓存函数和计算结果,避免重复计算。
示例代码:使用 useCallback
function Parent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Child onClick={increment} />;
}
总结
设计模式总结
模式 |
适用场景 |
优点 |
缺点 |
容器组件与展示组件 |
分离逻辑与 UI |
代码清晰,易于维护 |
可能增加组件层级 |
高阶组件 |
复用逻辑 |
逻辑复用,代码简洁 |
可能引入嵌套地狱 |
Render Props |
共享渲染逻辑 |
灵活,易于扩展 |
可能使代码复杂化 |
最佳实践
- 单一职责:每个组件只负责一个功能。
- 可复用性:尽量设计通用的组件。
- 高内聚低耦合:组件内部逻辑紧密,组件之间依赖较少。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)