react hooks useCallback useMemo的区别

最近在看react hooks,useState和useEffect较好理解,到useCallback和useMemo的时候,看官网不太懂,后来通过查阅资料,算是搞明白了,下面实例都是基于react-native,不过原理和react是一样的

1、useCallback

      useCallback返回一个函数,此函数具有memoized功效

     (1)使用场景:有一个父组件,含子组件,子组件接收一个函数作为props,通常,如果父组件更新了,子组件也会更新,但如果父组件更新的state,与子组件没关系,这时候,

子组件再更新是没有必要的。这时,可以借助useCallback返回函数,然后把这个函数作为props传给子组件,这样子组件可以避免不必要的更新。

     (2)疑问:大家可能会有疑问,可以在子组件里面使用PureComponent或Memo,这样如果子组件props不发生变化,子组件就不更新,如下:

    父组件:    

import React, {useState,useCallback} from "react";
import {View,Text,Button,StyleSheet} from 'react-native';
import Child1 from './Child1';
import Child2 from './Child2';

export default function CallBackHookDemo(){
    console.log('CallBackHookDemo 重新渲染------');
    const [count,setCount] = useState(0);
    const [show,setShow] = useState(true);
    const increment1 = ()=>{
        console.log('执行increment1函数');
        setCount(count+1);
    }
    return(
        <View style={styles.container}>
            <Text>CallBackHookDemo:{count}</Text>
            <Child1 increment={increment1}/>
            <Child2 gender={'0'} count={count}/>
            <Button title={'show切换'} onPress={(e) =>setShow(!show)}/>
        </View>
    )
}
const styles = StyleSheet.create({
    container:{
        paddingTop:40
    }
})

子组件:

import React,{memo} from 'react';
import {Button} from 'react-native';

const Child1 = memo(function Child1(props){
    console.log('Child1 重新渲染');
    return (
        <Button title={'button+1'} onPress={props.increment}/>
    )
})
export default Child1;

如上面代码:比如点击show切换按钮,这时候修改了show,原则上父组件重新render时,Child1组件是没有必要更新的,但是会更新。为什么呢?

原因是:子组件里面用的memo是浅比较,而子组件Child1的props是一个函数increment1,每次父组件rerender时,都会重新生成一个函数,所以浅比较毫无意义。

这时候就要用useCallback,将父组件修改如下:

import React, {useState,useCallback} from "react";
import {View,Text,Button,StyleSheet} from 'react-native';
import Child1 from './Child1';
import Child2 from './Child2';

export default function CallBackHookDemo(){
    console.log('CallBackHookDemo 重新渲染------');
    const [count,setCount] = useState(0);
    const [show,setShow] = useState(true);
    const increment2 = useCallback(()=>{
        console.log('执行increment2函数');
        setCount(count+1);
    },[count])
    return(
        <View style={styles.container}>
            <Text>CallBackHookDemo:{count}</Text>
            <Child1 increment={increment2}/>
            <Child2 gender={'0'} count={count}/>
            <Button title={'show切换'} onPress={(e) =>setShow(!show)}/>
        </View>
    )
}
const styles = StyleSheet.create({
    container:{
        paddingTop:40
    }
})

这时,切换show按钮,子组件Child1不会rerender,因为当count不改变时,Child1的props increment不会发生改变。这样节省了性能

2、useMemo

     useMemo返回一个值,此值具有memoized功效

   (1)使用场景:

    当组件内部某一渲染的数据,要通过计算得到,这个计算依赖于特定的state或props,我们就用useMemo来缓存这个渲染的数据,以致于我们在修改它们没有依赖的数据源的情况下,

多次调用这个计算函数,浪费性能

子组件Child2:

import React,{useState,useMemo,memo} from 'react';
import {Text} from 'react-native';

const Child2 = memo(function Child2(props){
    console.log('Child2 渲染----');
    const transferGender= (gender)=>{
        console.log(gender)
        return gender=='0' ?'男':'女';
    }
    const gender = useMemo(()=>
        transferGender(props.gender)
    ,[props.gender])
    return (
        <Text>{gender}:{props.count}</Text>
    )
})
export default Child2;

如上代码:父组件的count修改时,子组件Child2会rerender,但Child2的props gender没有发生变化,所以这时用useMemo,防止gender运算方法多次执行,浪费性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值