0
点赞
收藏
分享

微信扫一扫

React - 16 hooks之useMemo、useCallback、自定义Hook

1.useMemo

类似Vue中的计算属性

目前的问题是:当x改变时demo重新执行,方框中的逻辑也会执行,实际我只想当supNum和oppNum变化时执行计算出支持比率

React - 16 hooks之useMemo、useCallback、自定义Hook_react

只能作用于函数组件中

import React, { useState, useMemo } from "react";
import { Button } from 'antd';
import './Demo.less';

const Demo = function Demo() {
    let [supNum, setSupNum] = useState(10),
        [oppNum, setOppNum] = useState(5),
        [x, setX] = useState(0);

    /* 
     let xxx = useMemo(callback,[dependencies])
       + 第一次渲染组件的时候,callback会执行
       + 后期只有依赖的状态值发生改变,callback才会再执行
       + 每一次会把callback执行的返回结果赋值给xxx
       + useMemo具备“计算缓存”,在依赖的状态值没有发生改变,callback没有触发执行的时候,xxx获取的是上一次计算出来的结果
       和Vue中的计算属性非常的类似!!
     */
    let ratio = useMemo(() => {
        let total = supNum + oppNum,
            ratio = '--';
        if (total > 0) ratio = (supNum / total * 100).toFixed(2) + '%';
        return ratio;
    }, [supNum, oppNum]);

    return <div className="vote-box">
        <div className="main">
            <p>支持人数:{supNum}人</p>
            <p>反对人数:{oppNum}人</p>
            <p>支持比率:{ratio}</p>
            <p>x:{x}</p>
        </div>
        <div className="footer">
            <Button type="primary" onClick={() => setSupNum(supNum + 1)}>支持</Button>
            <Button type="primary" danger onClick={() => setOppNum(oppNum + 1)}>反对</Button>
            <Button onClick={() => setX(x + 1)}>干点别的事</Button>
        </div>
    </div>;
};

export default Demo;

React - 16 hooks之useMemo、useCallback、自定义Hook_react_02

2.useCallback

React - 16 hooks之useMemo、useCallback、自定义Hook_react_03

useCallback可以保证函数组件的每一次更新,不再把里面的小函数重新创建,用的都是第一次创建的!

React - 16 hooks之useMemo、useCallback、自定义Hook_react_04

React - 16 hooks之useMemo、useCallback、自定义Hook_react_05

React - 16 hooks之useMemo、useCallback、自定义Hook_react_06

import React, { useState, useCallback } from "react";
import { Button } from 'antd';
import './Demo.less';

/* 子组件 */
/* class Child extends React.PureComponent {
    render() {
        console.log('Child Render');
        return <div>
            我是子组件
        </div>;
    }
} */

const Child = React.memo(function Child(props) {
    console.log('Child Render');
    return <div>
        我是子组件
    </div>;
});

/* 父组件 */
// 诉求:当父组件更新的时候,因为传递给子组件的属性仅仅是一个函数「特点:基本应该算是不变的」,所以不想再让子组件也跟着更新了!
//   + 第一条:传递给子组件的属性(函数),每一次需要是相同的堆内存地址(是一致的) . 基于useCallback处理!!
//   + 第二条:在子组件内部也要做一个处理,验证父组件传递的属性是否发生改变,如果没有变化,则让子组件不能更新,有变化才需要更新 . 继承React.PureComponent即可「在shouldComponentUpdate中对新老属性做了浅比较」!! 函数组件是基于 React.memo 函数,对新老传递的属性做比较,如果不一致,才会把函数组件执行,如果一致,则不让子组件更新!!
const Demo = function Demo() {
    let [x, setX] = useState(0);

    // const handle = () => { };  //第一次:0x001  第二次:0x101  第三次:0x201 ...
    const handle = useCallback(() => { }, []); //第一次:0x001  第二次:0x001  第三次:0x001 ...

    return <div className="vote-box">
        <Child handle={handle} />
        <div className="main">
            <p>{x}</p>
        </div>
        <div className="footer">
            <Button type="primary" onClick={() => setX(x + 1)}>累加</Button>
        </div>
    </div>;
};

3.自定义hook

import React, { useState, useEffect } from "react";
import { Button } from 'antd';
import './Demo.less';

/* 
自定义Hook 
  作用:提取封装一些公共的处理逻辑
  玩法:创建一个函数,名字需要是 useXxx ,后期就可以在组件中调用这个方法!
*/
const usePartialState = function usePartialState(initialValue) {
    let [state, setState] = useState(initialValue);
    // setState:不支持部分状态更改的
    // setPartial:我们期望这个方法可以支持部分状态的更改
    const setPartial = function setPartial(partialState) {
        setState({
            ...state,
            ...partialState
        });
    };
    return [state, setPartial];
};

// 自定义Hook,在组件第一次渲染完毕后,统一干点啥事
const useDidMount = function useDidMount(title) {
    if (!title) title = 'React系统课';
    // 基于React内置的Hook函数,实现需求即可
    useEffect(() => {
        document.title = title;
    }, []);
};

const Demo = function Demo() {
    let [state, setPartial] = usePartialState({
        supNum: 10,
        oppNum: 5
    });

    const handle = (type) => {
        if (type === 'sup') {
            setPartial({
                supNum: state.supNum + 1
            });
            return;
        }
        setPartial({
            oppNum: state.oppNum + 1
        });
    };

    useDidMount('哈哈哈哈哈');

    return <div className="vote-box">
        <div className="main">
            <p>支持人数:{state.supNum}人</p>
            <p>反对人数:{state.oppNum}人</p>
        </div>
        <div className="footer">
            <Button type="primary" onClick={handle.bind(null, 'sup')}>支持</Button>
            <Button type="primary" danger onClick={handle.bind(null, 'opp')}>反对</Button>
        </div>
    </div>;
};

export default Demo;


举报

相关推荐

0 条评论