在React中,useContext 是一种非常方便的全局状态管理工具,它可以让我们在组件之间共享状态,而不需要通过层层传递 props。然而,当我们在一个大型的 React 应用中过度使用 useContext 时,可能会遇到性能问题。这是因为当一个 context 的值改变时,所有使用这个 context 的组件都会重新渲染,即使这个组件并不需要那个改变的值。

示例

举个例子,假设我们有一个全局的用户 context,它包含了用户的详细信息和一些设置:

const UserContext = React.createContext();

function App() {
const [user, setUser] = useState({ name: 'John', age: 30, theme: 'dark' }); const handleChangeName = () => {
setUser({ ...user, name: 'AAA' });
};
return (
<UserContext.Provider value={user}>
<Profile />
<Settings />
<button onClick={handleChangeName}>Change Name</button>
</UserContext.Provider>
);
} function Profile() {
const user = useContext(UserContext); return <h1>Welcome, {user.name}!</h1>;
} function Settings() {
const user = useContext(UserContext); return <div>Your current theme is: {user.theme}</div>;
}

在这个例子中,Profile 和 Settings 组件都使用了 UserContext。如果用户的主题改变了,Profile 组件也会重新渲染,即使它并不需要知道主题的信息。

改进方法

一种改进方法是使用 React 的 useMemouseCallback钩子来避免不必要的重新渲染。我们可以为每一个需要共享的状态创建一个单独的 context,然后使用 useMemo useCallback 来确保只有当这个状态改变时,使用这个状态的组件才会重新渲染:

const NameContext = React.createContext();
const ThemeContext = React.createContext(); function App() {
console.log('App');
const [user, setUser] = useState({ name: 'John', age: 30, theme: 'dark' }); const userName = useMemo(() => user.name, [user.name]);
const userTheme = useMemo(() => user.theme, [user.theme]); const handleChangeName = useCallback(() => {
setUser({ ...user, name: 'AAA' });
}, [user]); return (
<>
<NameContext.Provider value={userName}>
<ThemeContext.Provider value={userTheme}>
<Profile />
<Settings />
<button onClick={handleChangeName}>Change Name</button>
</ThemeContext.Provider>
</NameContext.Provider>
</>
);
}
const Profile = React.memo(function Profile() {
console.log('Profile');
const name = useContext(NameContext); return <h1>Welcome, {name}!</h1>;
}); const Settings = React.memo(function Settings() {
console.log('Settings');
const theme = useContext(ThemeContext); return <h1>Your current theme is: {theme}</h1>;
});

这样,只有当相关的状态改变时,对应的组件才会重新渲染,从而提高了性能。

举例useContext性能低下的样例,同时推荐用什么方法改进的更多相关文章

  1. Qt 鼠标样式特效探索样例(一)——利用时间器调用QWidget.move()函数

    Qt 鼠标样式特效探索样例(一)       心血来潮,突然想在Qt里玩一把鼠标样式,想到在浏览网页时,经常看到漂亮的鼠标动画,于是今天摸索着乱写个粗糙的demo,来满足自己的好奇心. 效果图 方案要 ...

  2. C++的性能C#的产能?! - .Net Native 系列《三》:.NET Native部署测试方案及样例

    之前一文<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATIVE初窥> 获得很多朋友支持和鼓励,也更让我坚定做这项技术的推广者,希望能让更多的朋友了解这项技术,于是先从官方 ...

  3. 【Scala篇】--Scala中Trait、模式匹配、样例类、Actor模型

    一.前述 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大. 模式匹配机制相当于java中的switch-case. 使用了case关键字的类定义就是样例类(case ...

  4. JPA入门样例(採用JPA的hibernate实现版本号)

    (1).JPA介绍: JPA全称为Java Persistence API ,Java持久化API是Sun公司在Java EE 5规范中提出的Java持久化接口.JPA吸取了眼下Java持久化技术的长 ...

  5. RESTful设计原则和样例(开发前后台接口)

    摘要 REST(表征性状态传输)设计风格;REST通常基于使用HTTP,URI协议和标准.使用URL标识资源,开发前后台接口.主要使用post,get方式 参考博文: http://www.cnblo ...

  6. CloudSim样例分析

    自带八个样例描述: cloudsim-2.1.1\examples目录下提供了一些CloudSim样例程序,每个样例模拟的环境如下: (1)CloudSimExample1.Java:创建一个一台主机 ...

  7. Ajax框架,DWR介绍,应用,样例

    使用Ajax框架 1. 简化JavaScript的开发难度 2. 解决浏览器的兼容性问题 3. 简化开发流程 经常使用Ajax框架 Prototype 一个纯粹的JavaScript函数库,对Ajax ...

  8. 最简单的视音频播放演示样例5:OpenGL播放RGB/YUV

    ===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频 ...

  9. VC6 鼠标钩子 最简单样例

    Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的.而钩子是Windows系统中非常重要的系统接口,用它能够截获并处理送给其它应用程序的消息,来完毕普通应用程序 ...

  10. SQL SERVER 变量的使用和样例

    定义和使用局部变量:说明: 局部变量是用户可自定义的变量. 作用范围仅在程序内部. 局部变量的名称是用户自定义的,命名的局部变量名要符合SQL Server 2000标识符命名规则=>以@开 在 ...

随机推荐

  1. CDN 引入 axios 和 qs 及其使用方法

    一些小项目,没必要搭建脚手架,直接以CDN的方式引入 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...

  2. mybatis案例程序

    前置工作 导包(mysql-connector-java.mybatis) 实体类 Mapper层 1.接口 public interface BookMapper { public Book get ...

  3. Linux开启SSH连接

    1. 查看是否安装 openssh-server:yum list installed | grep openssh-server 已安装成功,如下图 2.如果没有任何输出显示表示没有安装openss ...

  4. Kingbase ES 函数返回-return语句

    文章概要: 本文在https://www.cnblogs.com/kingbase/p/15703611.html 一文的基础上总结了Kingbase ES中函数能支持的return语句,整体上兼容o ...

  5. Linux服务器程序规范化

    Linux日志体系 rsyslogd守护进程既能接收用户进程输出的日志,又能接收内核日志.用户进程是通过调用syslog函数生成系统日志的.该函数将日志输出到一个UNIX本地域socket类型(AF_ ...

  6. #分块,可撤销并查集#洛谷 5443 [APIO2019]桥梁

    题目 分析 最直接的做法就是在线一边修改边权,询问直接全部重排, 然后用可撤销并查集维护连通块大小,这样时间复杂度为 \(O(qm)\) 同样尽量让大部分的边不需要修改边权,那么每 \(B\) 个操作 ...

  7. #费马小定理,BSGS#BZOJ 3285 离散对数解指数方程

    题目 求最小的正整数 \(x\) 满足 \(g^{ax+b}\equiv c\pmod p\) 其中 \(p\) 是一个质数, \(g,a,b,c\leq 10^{1000000},p\leq 2^{ ...

  8. JDK13的新特性:AppCDS详解

    目录 简介 基本步骤 JDK class文件归档 创建JDK class-data archive 使用JDK class-data archive启动应用程序 运行时间对比 应用程序class文件归 ...

  9. Redis和elasticsearch

    redis -----------NOSQL的对比和劣和应用场景参考好文http://www.redis.cn/articles/20181020003.html --------- -------- ...

  10. HarmonyOS智能座舱体验是怎样炼成的?立即查看

    原文链接:https://mp.weixin.qq.com/s/AGY2hAeXngtRrZFk0FXe5g,点击链接查看更多技术内容: 随着AITO问界M5热卖以及M7.M5 EV版本的陆续交付,A ...