前言
在react众多hook当中,useMemo也是很基础的一个钩子,这个钩子侧重点在于优化性能,在我理解来有点类似于vue的计算属性computed,今天为了加深印象让自己学的更深刻,就在这里写下自己对useMemo的一点理解。
这里首先贴下代码,然后枚举代码逐行理解。
type User = {
name: String;
age: number;
};
const Home: React.FC = () => {
const [name, setName] = useState<String>("");
const [user, setUser] = useState<User>({} as User);
const resUser = () => {
console.log("获取到了user");
return user;
};
const getUser = useMemo(resUser, [name]);
const setUserInfo = () => {
setName("jack");
setUser({ name: "jack", age: 26 });
};
return (
<div className="Home">
<Button type="primary" onClick={setUserInfo}>
memo
</Button>
<p>这里是:{getUser.name || "无"}</p>
</div>
);
};
分析
- 定义了User类型,分别包含name和age属性
- 函数式组件声明一个Home组件
- 定义两个state,一个是名字相关的state,一个是user信息相关的state
- 首先观察组件返回的HTML内容,包含一个Button 和
<p>标签。其中<p>标签包含了getUser方法,而getUser则是用useMemo进行缓存resUser这个方法,从而返回这个方法中的值。可以看出,返回的值是个User类型的对象。但是一开始user默认是{}空对象,所以<p>元素的内容就是:“这里是:无”。紧接着useMemo的第二个参数是更新依赖的数组,这里只放入了一个name,意思是只要name这个state发生了变化,就会触发resUser这个方法,从而返回新的user对象。 - 其次有个Button组件,点击事件是
setUserInfo,这个方法做了两件事:一是更新了名称,二是更新了user对象。而正是因为更新了name,所以会触发useMemo缓存的方法,即会重新执行resUser拿到最新的user对象,而刚好再setUserInfo中更新了user对象,所以resUser也返回了最新的user。此时的<p>元素的内容就是:“这里是:Jack”
到这里整个代码分析完了。
但是如果我们把setUserInfo这个方法中的setName("jack");这行代码去掉,也就是不更新名字了。还会出发resUser这个方法吗?答案肯定是不行的。因为useMemo的依赖更新就是name发生了改变才会触发相对应的方法。
这样做的好处
要想知道这样做的好处,那我们就写个不用useMemo可以实现的代码,改一下Home组件代码:
const Home: React.FC = () => {
const [user, setUser] = useState<User>({} as User);
const setUserInfo = () => {
setUser({ name: "jack", age: 26 });
};
const resUser = () => {
// ... other operate
return user;
};
const updateOther = () = > {
// ... other state updated
}
return (
<div className="Home">
<Button type="primary" onClick={setUserInfo}>
memo
</Button>
<p>这里是:{resUser().name || "无"}</p>
<Button type="primary" onClick={updateOther}>
update other
</Button>
</div>
);
};
比如像上面这种在Html里面引用方法。当你点击updateOther这个事件更新了其他的state会重新渲染这个组件的时候,resUser 这个方法会再次进入。如果遇到了复杂的逻辑,这对性能上是非常不友好的,明明没有改变关于user的state,却重新去获取user信息,这种消耗一定要避免。
所以用了useMemo之后,它所包含的方法必须依赖某个更新的项才能再次执行,否则就读取上一次缓存的值。这就是useMemo在优化性能上的好处。
最后
本文所列举的例子可能不是很恰当,明明有更简单的方法可以实现的。一样性能也更好。但笔者写这篇技术贴只是加强自己对react hook的理解。只要理解了能更好的运用到项目中就很好了。当然这也是笔者自己一点点拙劣的劣迹,后续有更深的理解会再次更新。