1.首先要了解什么是渲染
简单来说就是开发者不用考虑UI,只考虑修改状态,React会根据状态自动修改UI,渲染就是修改的过程。
2.React的不足
在每一次状态的修改(比如input框中的输入),都会导致重新渲染。要是代码中有一个很复杂的运算,这个运算也会跟着重新渲染。每渲染一次,就重新计算一次,耗时时间非常长(有的运算可能达到2秒之长)。有没有什么方法能够只在用到的时候才渲染呢?
3.useMemo
useMemo能够帮助我们解决这个问题
4.useMemo用法
useMemo(()=>{},[])应该传入两个参数,一是处理函数,二是依赖项,处理函数中返回的应当是一个结果(虽然也可以传函数,但是不建议这么做)
5.useMemo案例
这个案例是由两部分组成时钟和计算正整数包含的所有质数,不加useMemo,每增加1秒,计算就会重新执行。加上useMemo,只用当在Input框内输入数字,才会重新计算。
案例代码
import React, {useMemo} from 'react';
import format from 'date-fns/format';
function App() {
const [selectedNum, setSelectedNum] = React.useState(100);
const time = useTime();
const allPrimesRes = useMemo(()=>{
const allPrimes = [];
console.log('运行');
for (let counter = 2; counter < selectedNum; counter++) {
if (isPrime(counter)) {
allPrimes.push(counter);
}
}
return allPrimes;
}, [selectedNum])
return (
<>
<p className="clock">
{format(time, 'hh:mm:ss a')}
</p>
<form>
<label htmlFor="num">Your number:</label>
<input
type="number"
value={selectedNum}
onChange={(event) => {
// To prevent computers from exploding,
// we'll max out at 100k
let num = Math.min(100_000, Number(event.target.value));
setSelectedNum(num);
}}
/>
</form>
<p>
There are {allPrimesRes.length} prime(s) between 1 and {selectedNum}:
{' '}
<span className="prime-list">
{allPrimesRes.join(', ')}
</span>
</p>
</>
);
}
function useTime() {
const [time, setTime] = React.useState(new Date());
React.useEffect(() => {
const intervalId = window.setInterval(() => {
setTime(new Date());
}, 1000);
return () => {
window.clearInterval(intervalId);
}
}, []);
return time;
}
function isPrime(n){
const max = Math.ceil(Math.sqrt(n));
if (n === 2) {
return true;
}
for (let counter = 2; counter <= max; counter++) {
if (n % counter === 0) {
return false;
}
}
return true;
}
export default App;
可以看到上面的代码处理计算的函数被useMemo包裹上了,并且在[]里加了依赖项,只有在selectedNum变化时,才会重新计算
7.useCallback
useCallback和useMemo传入的参数是一样的,区别在于useMemo返回的是传入的函数结果,useCallback返回的是函数本身,也就是说useCallback不用return函数结果。
8.useCallback案例
主组件
import React, {useCallback} from 'react';
import MegaBoost from './MegaBoost';
function App() {
const [count, setCount] = React.useState(0);
const handleMegaBoost = useCallback(()=>{
setCount((currentValue) => currentValue + 1234);
}, []);
return (
<>
Count: {count}
<button
onClick={() => {
setCount(count + 1)
}}
>
Click me!
</button>
<MegaBoost handleClick={handleMegaBoost} />
</>
);
}
export default App;
MegaBoost组件
import React from 'react';
function MegaBoost({ handleClick }) {
console.log('Render MegaBoost');
return (
<button
className="mega-boost-button"
onClick={handleClick}
>
MEGA BOOST!
</button>
);
}
export default MegaBoost;
上面代码由三个部分组成
如果不加useCallback,无论点击哪个按钮,MegaBoost组件都会重新渲染,useCallback可以直接返回函数,不用return。
总结
以上就是useMemo和useCallback最简单的概念和用法,更深层次的概念以后会写文章详细说明,还有一些应用上的坑也会进行详解,感谢码友们的阅读。