blog
blog copied to clipboard
useCallback使用场景
useCallback使用场景
1、作为props,传递给子组件,为避免子元素不必要的渲染,需要配合React.Memo
或者useMemo
使用,否则无意义:
useMeno使用
:
import React,{useEffect,useState,useCallback,useMemo} from "react";
//子元素
const Child = () => {
const [count, setCount] = useState(() => callback());
alert('更新了');
useEffect(() => {
setCount(callback());
}, [callback]);
return <div>
{count}
</div>
}
//父元素
export default function App() {
const [count, setCount] = useState(1);
const [val, setVal] = useState('');
const callback = useCallback(() => {
return count;
}, [count]);
const Children = useMemo(() => <Child callback={callback}/>,[callback]);
return <div>
<h4>{count}</h4>
{
Children
}
<div>
<button onClick={() => setCount(count + 1)}>+</button>
<input value={val} onChange={event => setVal(event.target.value)}/>
</div>
</div>;
}
React.memo
使用:
// 子元素
const Child = React.memo(({ callback }) => {
const [count, setCount] = useState(() => callback());
alert('更新了');
useEffect(() => {
setCount(callback());
}, [callback]);
return <div>
{count}
</div>
})
//父元素
export default function App() {
const [count, setCount] = useState(1);
const [val, setVal] = useState('');
const callback = useCallback(() => {
return count;
}, [count]);
return <div>
<h4>{count}</h4>
<Child callback={callback}/>
<div>
<button onClick={() => setCount(count + 1)}>+</button>
<input value={val} onChange={event => setVal(event.target.value)}/>
</div>
</div>;
}
当我们再输入框输入的时候 子元素不会重新渲染;
2、作为useEffect
的依赖项,需要进行比较的时候才需要加上useCallback
;
//子元素
function Foo({bar}) {
React.useEffect(() => {
const options = bar
}, [bar])
return <div>foobar</div>
}
// 父级
function Blub() {
//源代码 const bar = {};
// 优化后的代码,使用useCallback包裹
const bar = React.useCallback(() => {}, [])
return <Foo bar={bar} />
}
总结:
记住useCallback
和useMemo
这两个内置的API
,都有特别的原因:
- 引用相等
- 昂贵的计算
什么是引用相等:
true === true // true
false === false // true
1 === 1 // true
'a' === 'a' // true
{} === {} // false
[] === [] // false
() => {} === () => {} // false
const z = {}
z === z // true
// NOTE: React 使用的是 Object.is, 和 === 非常类似
在React函数组件中定义一个对象时,它跟上次定义的相同对象,引用是不一样的(即使它具有所有相同值和相同属性);
那么,再React
中有两种引用相等很重要:
- React.memo;(也就是场景一)
- 依赖列表(场景二)
所以如下场景其实没有必要加上:
//这里的方法没有必要加上useCallback
const submit = () => {
//提交动作
};
<button onClick={submit}>点击提交</button>
所以有如下结论:只有当该方法会被拿去做引用对比的时候,才需要写useCallback,否则性能反而不会提升,普通的方法可以不必要加
;