头图

灵感来源来自一个面试官问我为什么hook函数不能在class类组件中使用?如何在class类组件中使用呢?
第一个问题你们自己可以百度一下晚上有,今天着重讲解一下第二个问题。
碰到这个问题首先要进行分析:
(1)hook函数在什么情况下可以调用?答:函数最外层可以调用Hook。
=>可不可以衍生一个函数代替class类组件调用?答:高阶组件就可以,因为高阶组件本身就是从高阶函数演变过来,高阶函数我的理解就是在高阶函数内调用传过来的参数(参数一般为回调函数)。高阶组件概念差不多,只不过,参数为组件,在react中组件的本质就是函数。。。
接下来,那么我们现在实现一个需求——————来个数字递增效果,然后到达某一个值时,停止。
原先错误的代码是这样的:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    
    <body>
        <div id="root"></div>
        <script src="https://cdn.bootcss.com/react/16.8.6/umd/react.development.js"></script>
 
        <script src="https://cdn.bootcss.com/react-dom/16.8.6/umd/react-dom.development.js"></script>
         
        <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.js"></script>
            <script type="text/babel">
                 const useState = React.useState;
                function useDateHook(){
                    return new Date().toDateString()
                }
                let timer = null;
                function withHooksHOC(Component){
                    return function (props){
                        const nowDate = useDateHook();
                        let [date,setDate] = useState(5);
                        timer = setInterval(()=>{
                            date++;
                            setDate(date)
                            /*if(date == 10){ //错误1
                                clearInterval(timer)
                            }*/ 
                        },1000)
                        if(date == 10){//错误2
                            console.log("exe")
                            clearInterval(timer)
                         }
                        return <Component date={date} 
 {...props} />;
                    }
                }
                 class DateCom extends React.Component{
                    render() {
                        return <p>date: {this.props.date}</p>;
                    }
                 }
                 let WithHooksHOCer = withHooksHOC(DateCom);
                class App extends React.Component{
                    constructor(props){
                        super(props)
                    }
                    render() {
                        return <WithHooksHOCer />;
                    }
                };
                
                ReactDOM.render(<App />,document.querySelector('#root'))
            </script>
    </body>
</html>

错误1和错误2其实错误点都差不多,都是date到达10的时候清掉当前定时器,但是每次HOOK setState函数每次更新数据都会生成一个定时器,慢慢的越来越多,导致页面崩溃!

在之前科普一下useRef作用?
1.获取DOM对象

2.保存数据
useRef相当于在函数式组件中添加了一个实例对象。useRef不会因为组件的更新而丢失数据,虽然组件进行了更新,但是通过useRef保存的数据并不随之发生改变。
3.ref对象的值发生改变之后,不会触发组件重新渲染。
https://blog.csdn.net/qq_30267753/article/details/125173931

下面是解决方案,这里用到了自定义hook函数,然后借鉴useEffect函数结合高阶函数(传递函数作为参数)和useRef作用(声明全局变量)的形式,并配置useEffect第二个参数,数组为空代表,组件挂载后和卸载后执行,[参数]表明,参数变化时,这点刚好契合定时函数定时传参的效果!即每次调用自定义hook函数的时候初始化生成一个回调函数的镜像,然后再另外一个副作用函数里代替执行回调函数内容,相当于直接在自定义hook函数中执行定时器效果。

下面是正确的完整的代码,可以在浏览器跑

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
</head>

<body>
    <div id="root"></div>
    <script src="https://cdn.bootcss.com/react/16.8.6/umd/react.development.js"></script>

    <script src="https://cdn.bootcss.com/react-dom/16.8.6/umd/react-dom.development.js"></script>

    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.js"></script>
    <script type="text/babel">
        const useState = React.useState;
        const useEffect = React.useEffect;
        const useRef = React.useRef;
        function useDateHook() {
            return new Date().toDateString()
        }
        function withHooksHOC(Component) {
            return function (props) {
            const nowDate = useDateHook();
            let [date, setDate] = useState(5);
            useInterval(() => {
                if(date < 10){
                    setDate(date + 1);
                }
            }, 1000)
            props = {
                date,
                nowDate
            }
            
            return <Component {...props} />
         }
        }
        function useInterval(callback,delay){
            const savedCallback = useRef();
            useEffect(() => {
                savedCallback.current = callback; //每次都初始化一个saveCallBack对象 用于后面副作用函数执行。
            }, [callback]); //第二个参数代表callback每次变化就就行,数组为空就代表组件挂载和卸载的时候执行
            useEffect(() => {
                let id = setInterval(() => {
                    savedCallback.current(); //执行回调
                }, delay);
                return function (){
                    clearInterval(id);
                }
            }, [delay])
        }
        class DateCom extends React.Component {
            render() {
                return <div id="box"><p>date: {this.props.date}</p><p>props:{this.props.nowDate}</p></div>       
            }
        }
        
        let WithHooksHOCer = withHooksHOC(DateCom);
        class App extends React.Component {
            constructor(props) {
                super(props)
            }
            render() {
                return <WithHooksHOCer />;
            }
        };

        ReactDOM.render(<App />, document.querySelector('#root'))
    </script>
 </body>
</html>

参考文献:
https://www.52dianzi.com/category/article/37/689191.html
https://baijiahao.baidu.com/s?id=1744203108622010543&wfr=spid...


阳哥
14 声望0 粉丝

一个code爱好者,一个户外运动的爱好者,一个喜欢音乐的爱好者。