我们都知道,当父组件的状态值(state)和属性值(props)发生改变后,子组件会随之重新渲染。
但是实际开发过程中,某些场景我们并不想让子组件重新渲染,以提高性能。一起看下面的例子:
import React, { useState, memo } from 'react';
import { Button, Card, Alert } from 'antd';
// 子组件
const Child = () => {
console.log("渲染了子组件");
return (
<Alert message='我是一个简单的子组件' />
);
}
// 父组件
const Parent = () => {
const [count, setCount] = useState(0);
// 按钮点击事件
const handleClick = () => {
setCount(count + 1);
}
return (
<Card>
<p>{count}</p>
<p><Button onClick={handleClick}>点击+1</Button></p>
<Child />
</Card>
);
}
export default Parent;
我们的目的,仅仅是点击+1时,让数字增加1,即父组件渲染。但是很显然,每次父组件重新渲染后,子组件也随之渲染了。既然子组件没有任何改动,为什么还让它渲染呢?
出于优化考虑:
我们期待的结果是当子组件的state和props没有发生改变时,即使父组件重新渲染,也不要渲染子组件。
解决办法是,在子组件的最外层用React.memo,修改如下:
import React, { useState, memo } from 'react';
import { Button, Card, Alert } from 'antd';
// 子组件:用React.memo包裹
const Child = memo(() => {
console.log("渲染了子组件");
return (
<Alert message='我是一个简单的子组件' />
);
})
// 父组件
const Parent = () => {
const [count, setCount] = useState(0);
// 按钮点击事件
const handleClick = () => {
setCount(count + 1);
}
return (
<Card>
<p>{count}</p>
<p><Button onClick={handleClick}>点击+1</Button></p>
<Child />
</Card>
);
}
export default Parent;
当我们再次点击+1时,控制台并没有打印出:“渲染了子组件”,表明子组件并没有渲染。
思考:
import React, { useState, memo } from 'react';
import { Button, Card, Alert } from 'antd';
// 子组件
const Child = memo(({ textInfo }) => {
console.log("渲染了子组件");
return (
<Alert message='我是一个简单的子组件' />
);
})
// 父组件
const Parent = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("你好,世界!");
// 按钮点击事件
const handleClick = () => {
setCount(count + 1);
}
return (
<Card>
<p>{count}</p>
<p><Button onClick={handleClick}>点击+1</Button></p>
<Child textInfo={{ text }} />
</Card>
);
}
export default Parent;
我们增加一个变量 text ,当我们点击+1,发现子组件在控制台还是打印出:“渲染了子组件”。有的小伙伴可能该问了,text 的值一直是:“你好,世界!”,props并没有发生改变,子组件为啥还是会重新渲染呢?难道是React.memo失效了?
如果我把
<Child textInfo={{ text }} />
更改为:
<Child textInfo={ text } />
结果是不是会一样呢?
如果不懂怎么解决上述问题,嘿嘿。那就老实和我一起继续往下学习吧:React Hook – useMemo