• useCallback 和 useMeme 具体使用场景介绍


    一、先说一下react

    react是基于数据是不可变的(每次setState都会返回一个新数据),这也是为什么需要setState()来更新数据而不能使用像vue的this.state = newState的形式更新数据的原因,其实你用this.state=newState确实可以改数据,但是react不知道数据变了。

    二、useMemo、useEffect的执行时机对比

    useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。

    三、useMemo的使用场景

    使用过vue的话,你可以把它理解成vue里面的computed,是一种数据的缓存,而这个缓存依赖后面的第二个参数数组,如果这个数组里面传入的数据不变,那么这个useMemo返回的数据是之前里面return的数据。

    在具体项目中,如果你的页面上展示的数据是通过某个(某些)state计算得来的一个数据,那么你每次这个组件里面无关的state变化引起的重新渲染,都会去计算一下这个数据,这时候就需要用useMemo(()=>{}, [])去包裹你的计算的方法体,这样那些无关的state改变引起的渲染不会重新计算这个方法体,而是返回之前计算的结果,达到一种缓存的效果。

    export default function WithMemo() {
        const [count, setCount] = useState(1);
        const [val, setValue] = useState('');
        const expensive = useMemo(() => {
            console.log('compute');
            let sum = 0;
            for (let i = 0; i < count * 100; i++) {
                sum += i;
            }
            return sum;
        }, [count]);
     
        return <div>
            <h4>{count}-{expensive}</h4>
            {val}
            <div>
                <button onClick={() => setCount(count + 1)}>+c1</button>
                <input value={val} onChange={event => setValue(event.target.value)}/>
            </div>
        </div>;
    }

    四、useCallback使用场景

    useCallback跟useMemo比较类似,但它返回的是缓存的函数。

    hooks组件state改变后会引起父组件的重新渲染,而每次重新渲染都会生成一个新函数,所以react子组件props在浅比较的时候就会认为props改变了,引起子组件不必要的渲染。

    使用场景是:有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。

    为什么useCallback需要配合React.memo来使用?

    react的Hooks组件对props的浅比较是在memo里面比较的(类组件是在shouldComponentUpdate里面),如果没有memo,那么你使用useCallback就没啥意义,反而浪费性能(因为useCallback来包裹函数也是需要开销的)。因为子组件还是会重新渲染。

    function APP() {
    
        const [value, setValue] = useState(123)
        const [otherValue, setOtherValue] = useState(999)
    
        const changeValue = useCallback(() => {
            setValue(value => value+1)
        }, [])
        
        console.log('APP');
    
        return (
            <div>
                <div>与Message渲染无关的数据==={otherValue}</div>
                <br />
                <button onClick={() => setOtherValue(value => value-=5)}>改变无关的数据</button>
                <br />
                <br />
                <Message value={value} changeValue={changeValue} />
            </div>
        )
    }
    
    const Message = memo(
        function Message({value, changeValue}) {
        
            console.log('Message');
        
            return (
                <div>
                    <button onClick={changeValue}>改变有关数据</button>
                    <p>与Message渲染有关的数据{value}</p>
                </div>
            )
        }
    )
  • 相关阅读:
    iView -- TimePicker 自定义修改时间选择器选择时间面板样式
    Go语言--容器:存储和组织数据的方式--数组、切片
    php递归实现一维数组转为指定树状结构 --- 省市区处理
    Go语言--基础语法笔记
    Mongodb 安装错误汇总
    GIt -- git push 远程分支老是需要重新输入公钥密码问题处理?
    GIt -- fatal: refusing to merge unrelated histories 问题处理
    Linux -- Centos6 yum安装相关问题与处理
    Linux -- Xshell ,Xftp远程连接中文乱码怎么解决?
    Laravel 多数据库配置及查询操作
  • 原文地址:https://www.cnblogs.com/art-poet/p/14781741.html
Copyright © 2020-2023  润新知