介绍

状态管理,主要介绍下:useCountDown(倒计时)、useBoolean(布尔管理)、useToggle(两种状态切换)、MockSet(Set类型管理)、Object(Object类型管理)、useCounter(数字类型管理)、useNetwork(网络连接状态)、MockWhyDidYouUpdate(什么导致渲染 render)

在线观看: Domesy/State

布尔值

useBoolean:切换布尔值

  • toggle:触发可改变其状态值
  • setTrue:将状态设置为true
  • setFalse:将状态设置为false

    代码演示

    image.png

    详细代码

    1. import React from 'react';
    2. import { Button } from 'antd';
    3. import { useBoolean } from 'ahooks';
    4. const Mock: React.FC<any> = () => {
    5. const [state, { toggle, setTrue, setFalse }] = useBoolean(true);
    6. return (
    7. <>
    8. <p>状态值:{JSON.stringify(state)}</p>
    9. <div style={{display: 'flex', justifyContent: 'flex-start'}}>
    10. <Button type='primary' onClick={() => toggle()}>
    11. 切换
    12. </Button>
    13. <Button type='primary' onClick={() => setFalse()} style={{margin:'0 30px'}}>
    14. 设置false
    15. </Button>
    16. <Button type='primary' onClick={() => setTrue()}>
    17. 设置true
    18. </Button>
    19. </div>
    20. </>
    21. );
    22. };
    23. export default Mock;

    两种状态切换

    useToggle: 普通用法月 useBoolean 的用法一致,高级用法,可支持两种状态之间的切换``

  • state:状态值

  • toggle:触发状态更改的函数
  • setLeft:设置为 defaultValue
  • setRight:设置为 reverseValue

    代码演示

    image.png

    详细代码

    1. import React from 'react';
    2. import { Button } from 'antd';
    3. import { useToggle } from 'ahooks';
    4. const Mock: React.FC<any> = () => {
    5. const [state, { toggle, setLeft, setRight }] = useToggle('Hello', 'World');
    6. const [boolean , { toggle:toggleBool }] = useToggle(false);
    7. return (
    8. <>
    9. <div style={{fontWeight: 'bolder'}}>基础用法(与useBoolean使用一直):</div>
    10. <div style={{marginTop: 8, fontWeight: 'bolder'}}>状态:{JSON.stringify(boolean)}</div>
    11. <div style={{justifyContent: 'flex-start', display:'flex', marginTop: 8}}>
    12. <Button type='primary' style={{marginRight: 8}} onClick={() => toggleBool()}>切换</Button>
    13. <Button type='primary' style={{marginRight: 8}} onClick={() => toggleBool(false)}>切换1</Button>
    14. <Button type='primary' style={{marginRight: 8}} onClick={() => toggleBool(true)}>切换2</Button>
    15. </div>
    16. <div style={{marginTop: 8, fontWeight: 'bolder'}}>高级用法:</div>
    17. <div style={{marginTop: 8}}>两种状态切换:{state}</div>
    18. <div style={{justifyContent: 'flex-start', display:'flex', marginTop: 8}}>
    19. <Button type='primary' style={{marginRight: 8}} onClick={() => toggle()}>切换</Button>
    20. <Button type='primary' style={{marginRight: 8}} onClick={() => toggle('Hello1')} >切换为 hello</Button>
    21. <Button type='primary' style={{marginRight: 8}} onClick={() => toggle('World')} >切换为 World</Button>
    22. </div>
    23. <div style={{justifyContent: 'flex-start', display:'flex', marginTop: 8}}>
    24. <Button type='primary' style={{marginRight: 8}} onClick={() => setLeft()} >设置为Hello</Button>
    25. <Button type='primary' style={{marginRight: 8}} onClick={() => setRight()} >设置为World</Button>
    26. </div>
    27. </>
    28. );
    29. };
    30. export default Mock;

    可管理的Set类型

    useSet: 包含 set(Set对象),有功能:添加元素(add)、移除元素(remove)、判断元素是否存在(hsa)、重置(reset)功能

  • set: Set 对象

  • add: 添加元素
  • has:判断是否存在元素
  • remove: 移除元素
  • reset:重置为默认值
  • initialValue: 传入默认的 Set 参数

    代码演示

    image.png

    详细代码

    1. import React from 'react';
    2. import { Button } from 'antd';
    3. import { useSet, useCounter } from 'ahooks';
    4. const Mock: React.FC<any> = () => {
    5. const [set, { add, has, remove, reset }] = useSet(['Hello']);
    6. const [current, { inc, reset:countReset }] = useCounter(1);
    7. return (
    8. <>
    9. <div style={{justifyContent: 'flex-start', display:'flex',}}>
    10. <Button type='primary' style={{marginRight: 8}} onClick={() => {
    11. inc()
    12. add(String(Method.getDate({add: current})))
    13. }}>
    14. 日期加1
    15. </Button>
    16. <Button type='primary' style={{marginRight: 8}} onClick={() => remove('Hello')} disabled={!has('Hello')} >删除 Hello</Button>
    17. <Button type='primary' style={{marginRight: 8}} onClick={() => {reset(); countReset()}} >重置</Button>
    18. </div>
    19. <div style={{ marginTop: 16 }}>
    20. <pre>{JSON.stringify(Array.from(set), null, 2)}</pre>
    21. </div>
    22. </>
    23. );
    24. }
    25. export default Mock;

    管理Object类型

    useSetState: 简而言之,就是类组件的 this.setState, 他可以接收任意组件的类型

    代码演示

    image.png

    详细代码

    ```typescript import React from ‘react’; import { Button } from ‘antd’; import { useSetState } from ‘ahooks’;

    interface State { hello: string; count: number;

  1. [key: string]: any;

}

const Mock: React.FC = () => { const [state, setState] = useSetState({ hello: ‘’, count: 0, });

  1. return (
  2. <>
  3. <div style={{justifyContent: 'flex-start', display:'flex',}}>
  4. <Button type='primary' style={{marginRight: 8}} onClick={() => setState({ hello: 'domesy' })}>
  5. 设置 hello
  6. </Button>
  7. <Button type='primary' style={{marginRight: 8}} onClick={() => setState({ domesy: '欢迎👏🏻' })} >设置任意值,domesy</Button>
  8. <Button type='primary' style={{marginRight: 8}} onClick={() => setState((prev) => ({ count: prev.count + 1 }))} >加1</Button>
  9. </div>
  10. <pre>{JSON.stringify(state, null, 2)}</pre>
  11. </>
  12. );

};

export default Mock;

  1. <a name="yultY"></a>
  2. ## 数字类型
  3. - **useCounter: 数字管理器**
  4. - **可以设置数字的范围,如:最大值、最小值,并有操作 增加,减少,设置,重置四个功能**
  5. - **无论是初始值还是,增加,减少,所设定的值在 最大、最小值之间,如过高于最大值,则 current 为最大值,反之亦然**
  6. <a name="otMGL"></a>
  7. ### 代码演示
  8. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/310196/1636104324925-ab4ace6f-2de3-4c52-8f10-4745c60ac35c.png#clientId=uffbaa07b-2305-4&from=paste&height=160&id=udad35304&margin=%5Bobject%20Object%5D&name=image.png&originHeight=160&originWidth=932&originalType=binary&ratio=1&size=20908&status=done&style=none&taskId=u7887a00d-e155-41d3-ae5e-7318e2585d9&width=932)
  9. <a name="QMYUS"></a>
  10. ### 详细代码
  11. ```typescript
  12. import React from 'react';
  13. import { Button } from 'antd';
  14. import { useCounter } from 'ahooks';
  15. const Mock: React.FC<any> = () => {
  16. const [current, { inc, dec, set, reset }] = useCounter(100, { min: 1, max: 10 });
  17. return (
  18. <>
  19. <div>数字:{ current } 范围(最小:1,最大为:10)</div>
  20. <div style={{display: 'flex',justifyContent: 'flex-start', marginTop: 8}}>
  21. <Button type="primary" style={{marginRight: 8}} onClick={() => inc()}>加1</Button>
  22. <Button type="primary" style={{marginRight: 8}} onClick={() => inc(2)}>加2</Button>
  23. <Button type="primary" style={{marginRight: 8}} onClick={() => dec()}>减一</Button>
  24. <Button type="primary" style={{marginRight: 8}} onClick={() => set(3)}>设置为3</Button>
  25. <Button type="primary" onClick={() => reset()}>重置</Button>
  26. </div>
  27. </>
  28. );
  29. };
  30. export default Mock;

倒计时

  • useCountDown: 倒计时
  • 首先有两个值,一个是目标值(targetDate),一个是设置值,如果不设置初始值(setTargetDate),则默认为现在
  • 会自动计算离目标值的天月周等(formattedRes),同时也有据目标值的时间戳(countdown),注意这里的单位是毫秒,所以精确到秒为 Math.round(countdown / 1000)
  • 有常用的倒计时功能,并能控制停止时所触发的函数(onEnd)

    代码演示

    image.png

    详细代码

    ```typescript import React, { useEffect } from ‘react’; import { Button, message } from ‘antd’; import { useBoolean } from ‘ahooks’; import { Method } from ‘@/utils’; const CountDownTest1: React.FC = () => { const [countdown, setTargetDate, formattedRes] = useCountDown({

    1. targetDate: Method.getDate({add: 3}),

    });

    useEffect(() => {

    1. setTargetDate(Method.getDate({add: 2}))

    }, [])

    const { days, hours, minutes, seconds, milliseconds } = formattedRes;

    return

    设置时间为后天,目标时间为大后天:{days} 天, {hours} 小时 {minutes} 分钟 {seconds} 秒 {milliseconds}
    }

    const CountDownTest2: React.FC = () => { const [countdown, setTargetDate, formattedRes] = useCountDown({

    1. onEnd: () => {
    2. message.info('已停止!')
    3. }

    });

    return

    1. 倒计时:
    2. <Button style={{margin: '0 24px'}} type='primary' onClick={() => {
    3. setTargetDate(Date.now() + 60000);
    4. }}>{countdown === 0 ? '倒计时' : "Math.round(countdown / 1000)" +s}</Button>
    5. <Button onClick={() => {
    6. setTargetDate(undefined);
    7. }}>停止 </Button>

    }

    const Mock: React.FC = () => { const [countdown, setTargetDate, formattedRes] = useCountDown({

    1. targetDate: Method.getDate({add: 1}),

    });

    const { days, hours, minutes, seconds, milliseconds } = formattedRes;

    return (

    1. <>
    2. <div>距离下一天0点的数据:{days} 天, {hours} 小时 {minutes} 分钟 {seconds} 秒 {milliseconds}</div>
    3. <div></div>
    4. <CountDownTest1 />
    5. <div></div>
    6. <CountDownTest2 />
    7. </>

    };

    export default Mock;

  1. <a name="ZiOWN"></a>
  2. ## 网络连接状态
  3. - **useNetwork: 网络连接状态的一些信息**
  4. <a name="byeJt"></a>
  5. ### 代码演示
  6. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/310196/1636104509474-9a15d188-bfad-482f-9994-ae35996f4873.png#clientId=uffbaa07b-2305-4&from=paste&height=444&id=uda88b1ce&margin=%5Bobject%20Object%5D&name=image.png&originHeight=444&originWidth=802&originalType=binary&ratio=1&size=65710&status=done&style=none&taskId=u45291b93-f396-4960-8f7c-d2f1d83549e&width=802)
  7. <a name="fPHyz"></a>
  8. ### 详细代码
  9. ```typescript
  10. import React from 'react';
  11. import { Button } from 'antd';
  12. import { useCounter } from 'ahooks';
  13. const Mock: React.FC<any> = () => {
  14. const [current, { inc, dec, set, reset }] = useCounter(100, { min: 1, max: 10 });
  15. return (
  16. <>
  17. <div>数字:{ current } 范围(最小:1,最大为:10)</div>
  18. <div style={{display: 'flex',justifyContent: 'flex-start', marginTop: 8}}>
  19. <Button type="primary" style={{marginRight: 8}} onClick={() => inc()}>加1</Button>
  20. <Button type="primary" style={{marginRight: 8}} onClick={() => inc(2)}>加2</Button>
  21. <Button type="primary" style={{marginRight: 8}} onClick={() => dec()}>减一</Button>
  22. <Button type="primary" style={{marginRight: 8}} onClick={() => set(3)}>设置为3</Button>
  23. <Button type="primary" onClick={() => reset()}>重置</Button>
  24. </div>
  25. </>
  26. );
  27. };
  28. export default Mock;

什么导致渲染了render

useWhyDidYouUpdate: 他可以帮助我们开发快速定位是那些参数导致的渲染,然后让其尽量避免渲染,从而优化星呢性能

代码演示

image.png

详细代码

  1. import React,{ useState } from 'react';
  2. import { Button } from 'antd';
  3. import { useWhyDidYouUpdate } from 'ahooks';
  4. const Demo: React.FC<{ count: number }> = (props) => {
  5. const [randomNum, setRandomNum] = useState(Math.random());
  6. useWhyDidYouUpdate('useWhyDidYouUpdateComponent', { ...props, randomNum });
  7. return (
  8. <div>
  9. <p>父传子的 number: {props.count}</p>
  10. <div>子组件的随机数:{randomNum}</div>
  11. <Button type="primary" style={{margin: '8px 0'}} onClick={() => setRandomNum(Math.random)}>更改子组件🎲</Button>
  12. </div>
  13. )
  14. }
  15. const Mock: React.FC<any> = () => {
  16. const [count, setCount] = useState(0);
  17. return (
  18. <>
  19. <div style={{fontWeight: 'bolder', marginBottom: 8}}>需要在控制台查看是什么引起的 render</div>
  20. <Demo count={count} />
  21. <div style={{justifyContent: 'flex-start', display:'flex', marginTop: 8}}>
  22. <Button type='primary' style={{marginRight: 8}} onClick={() => setCount((prevCount) => prevCount + 1)}>加1</Button>
  23. <Button type='primary' style={{marginRight: 8}} onClick={() => setCount((prevCount) => prevCount - 1)} >减1</Button>
  24. </div>
  25. </>
  26. );
  27. };
  28. export default Mock;