Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

自定义 Hook #33

Open
ZhangHanwen96 opened this issue Mar 23, 2021 · 0 comments
Open

自定义 Hook #33

ZhangHanwen96 opened this issue Mar 23, 2021 · 0 comments

Comments

@ZhangHanwen96
Copy link
Owner

ZhangHanwen96 commented Mar 23, 2021

------------------------------------Reference-----------------------------------

  • memo包裹functional component达到pureComponent效果
  • useMemo可以帮我们将变量缓存起来,useCallback可以缓存回调函数
  • 平时还会涉及到获取组件dom和使用内部闭包变量的情景,这个时候我们就可以使用useRef, ref 对象在组件的整个生命周期内保持不变

useDebounce

import { useEffect, useRef } from 'react'

const useDebounce = (fn, ms=30, deps=[]) => {
    let timeout = useRef();

    useEffect(() => {
        if(timeout.current) clearTimeout(timeout.current)
        timeout.current = setTimeout(() => {
            fn()
        }, ms)
    }, deps)

    const cancel = () => {
        clearTimeout(timeout.current)
        timeout = null
    }

    return [cancel]
}





import { useDebounce } from 'hooks'
    const Home = (props) => {
        const [a, setA] = useState(0)
        const [b, setB] = useState(0)
        const [cancel] = useDebounce(() => {
                setB(a)
            }, 2000, [a])

    const changeIpt = (e) => {
        setA(e.target.value)
    }

    return <div>
        <input type="text" onChange={changeIpt} />
        { b } { a }
    </div>
}

useThrottle

const useThrottle = (fn, ms=30, deps=[]) => {
    let timeout = useRef();

    useEffect(() => {
        if(timeout.current) return
        timeout.current = setTimeout(() => {
            fn()
            timeout.current = null
        }, ms)
    }, deps)

    const cancel = () => {
        clearTimeout(timeout.current)
        timeout = null
    }

    return [cancel]
}

useUpdate

我们都知道如果想让组件重新渲染,我们不得不更新state,但是有时候业务需要的state是没必要更新的,我们不能仅仅为了让组件会重新渲染而强制让一个state做无意义的更新,所以这个时候我们就可以自定义一个更新的hooks来优雅的实现组件的强制更新,实现代码如下:

import { useState } from 'react'

const useUpdate = () => {
    const [, setFlag] = useState()
    const update = () => {
        setFlag(Date.now())
    }
  
    return update
  }

export default useUpdate



const Home = (props) => {
  // ...
  const update = useUpdate()
  return <div>
    {Date.now()}
    <div><button onClick={update}>update</button></div>
  </div>
}

useScroll

const useScroll = (scrollRef) => {
    const [pos, setPos] = useState([0, 0]);

    useEffect(() => {
        function handleScroll(e) {
            setPos([scrollRef.current.scrollLeft, scrollRef.current.scrollTop]);
        }

        scrollRef.current.addEventListener("scroll", handleScroll, false);

        return () => {
            scrollRef.current.removeEventListener(
                "scroll",
                handleScroll,
                false
            );
        };
    }, []);

    return pos;
};

export default useScroll;

由以上代码可知,我们在钩子函数里需要传入一个元素的引用,这个我们可以在函数组件中采用ref和useRef来获取到,钩子返回了滚动的x,y值,即滚动的左位移和顶部位移,具体使用如下:

import React, { useRef } from "react";

import { useScroll } from "hooks";
const Home = (props) => {
    const scrollRef = useRef(null);
    const [x, y] = useScroll(scrollRef);

    return (
        <div>
            <div ref={scrollRef}>
                <div className='innerBox'></div>
            </div>
            <div>
                {x}, {y}
            </div>
        </div>
    );
};

useUpdate

我们都知道如果想让组件重新渲染,我们不得不更新state,但是有时候业务需要的state是没必要更新的,我们不能仅仅为了让组件会重新渲染而强制让一个state做无意义的更新,所以这个时候我们就可以自定义一个更新的hooks来优雅的实现组件的强制更新,实现代码如下:

import { useState } from 'react'

const useUpdate = () => {
    const [, setFlag] = useState()
    const update = () => {
        setFlag(Date.now())
    }
  
    return update
  }



const Home = (props) => {
  // ...
  const update = useUpdate()
  return <div>
    {Date.now()}
    <div><button onClick={update}>update</button></div>
  </div>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant