关于react项目的优化,react提供了memo,useMemo和useCallback
下面来看看具体怎么使用吧。
React.memo
父元素触发更新后,其子元素也会跟着更新;但是有时候子元素确实没必要重新渲染,故使用 React.memo
可减少重新渲染次数。
使用格式:
// 使用格式
const MyComponent = (props) => {
/* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
/*
如果把 nextProps 传入 render 方法的返回结果与
将 prevProps 传入 render 方法的返回结果一致则返回 true,
否则返回 false
*/
}
export const MyComponentMemo = React.memo(MyComponent, areEqual);
一个简单的栗子:
运行可看出:在加载完成后打印 SecondChild子组件?
的次数明显多于 子组件?
并且每次点击按钮加1时,即使 SecondChild
组件没有依赖 count
还是会打印 SecondChild子组件?
,说明在重新渲染,但是 Child
组件则不会。(是不是挺好理解的表情🤣
import React, { useState, useEffect, useMemo } from 'react'
const Child = React.memo((props) => {
console.log('子组件?')
return(
<div>我是一个子组件</div>
);
})
const SecondChild = (props) => {
console.log('SecondChild子组件?')
return(
<div>我是第二个子组件</div>
);
}
const Page = () => {
const [count, setCount] = useState(0);
return (
<>
<button onClick={(e) => { setCount(count+1) }}>加1</button>
<p>count:{count}</p>
<Child />
<SecondChild />
</>
)
}
export default Page
useMemo
看到 useMemo
,想着会不会跟 React.memo
有啥关系,其实它们两个是可以配合着一起使用的。
useMemo
的格式跟 useEffect
是一样的,他们之间最大的区别是 useEffect
会用于处理副作用,而useMemo
是其依赖的变量发生改变时再次执行,然后返回缓存的变量;另外 useMemo
会在组件第一次渲染的时候执行;
import React, { useState, useEffect, useMemo, useCallback } from 'react'
const Child = React.memo((props) => {
console.log('子组件?')
return(
<>
<div>我是一个子组件, number={props.number}</div>
</>
);
})
const SecondChild = (props) => {
console.log('SecondChild子组件?')
return(
<div>我是第二个子组件</div>
);
}
const Page = () => {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(0);
// 返回的是一个值
const sum = useMemo(() => {
console.log("sum")
return count * count
}, [count])
const square = () => {
console.log("square")
return count * count
}
return (
<>
<button onClick={(e) => { setCount(count+1) }}>加1</button>
<p>count:{count}</p>
<button onClick={(e) => { setNumber(number+1) }}>加1</button>
<p>number:{number}</p>
<div>count平方sum:{sum}</div>
<div>count平方square:{square()}</div>
<Child number={number} />
<SecondChild />
</>
)
}
export default Page
运行上面的例子,可以发现,当 count
加一时,会打印 sum
和 square
;当 number
加一时,只会打印 square
;所以如果获取的数是很耗性能时,使用 useMemo
可以避免性能不必要的浪费;
useCallback
如果你学会了 useMemo
,那么 useCallback
你也可以轻松掌握;useCallback
与 useMemo
是一样使用的,不同的是 useCallback
返回的是缓存的函数;
import React, { useState, useEffect, useMemo, useCallback } from 'react'
const Child = React.memo((props) => {
console.log('子组件?')
const [count, setCount] = useState(0);
// 监听getValue的改变或者直接getValue()
/* useEffect(() => {
setCount(props.getValue())
}, [props.getValue]) */
return(
<>
<div>我是一个子组件, number={props.number}</div>
<div>获取value: {props.getValue()}</div>
{/* <div>获取value: {count}</div> */}
</>
);
})
const SecondChild = (props) => {
console.log('SecondChild子组件?')
return(
<div>我是第二个子组件</div>
);
}
const Page = () => {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(0);
const [value, setValue] = useState(0);
// 返回的是一个函数
const getValue = useCallback(() => {
console.log("getValue")
return value
}, [value])
/* const getValue = () => {
return value
} */
return (
<>
<button onClick={(e) => { setCount(count+1) }}>加1</button>
<p>count:{count}</p>
<button onClick={(e) => { setNumber(number+1) }}>加1</button>
<p>number:{number}</p>
<button onClick={(e) => { setValue(value+1) }}>加1</button>
<p>value:{value}</p>
<Child getValue={getValue} number={number} />
<SecondChild />
</>
)
}
export default Page