zoukankan      html  css  js  c++  java
  • react hooks的缺点(针对状态不同步和没有生命周期)

    react在16.8中加入了hooks,可以在函数组件中添加一些有自己独立上下文管理的状态(useState),不再依赖于类组件,同时一些逻辑也可以放到hooks中来复用(useEffects)。

    不巧,最近react项目里用到了hooks,就拿来练练手,在开发中遇到了点问题,我就说说我的问题和解决方案吧
    1.没有生命周期。
    2.没有回调函数。

    缺点

    一、状态不同步
    函数的运行是独立的,每个函数都有一份独立的作用域。函数的变量是保存在运行时的作用域里面,当我们有异步操作的时候,经常会碰到异步回调的变量引用是之前的,也就是旧的(这里也可以理解成闭包)如下:

    import React, { useState } from "react";
    ​
    const Counter = () => {
      const [counter, setCounter] = useState(0);
    ​
      const onAlertButtonClick = () => {
        setTimeout(() => {
          alert("Value: " + counter);
        }, 3000);
      };
    ​
      return (
        <div>
          <p>You clicked {counter} times.</p>
          <button onClick={() => setCounter(counter + 1)}>Click me</button>
          <button onClick={onAlertButtonClick}>
            Show me the value in 3 seconds
          </button>
        </div>
      );
    };
    ​
    export default Counter;
    

    当你点击Show me the value in 3 seconds的后,紧接着点击Click me使得counter的值从0变成1。三秒后,定时器触发,但alert出来的是0(旧值),但我希望的结果是当前的状态1。
    这时我们可以用useEffect来实现我们的需求

    import React, { useState, useRef, useEffect } from "react";
    ​
    const Counter = () => {
      const [counter, setCounter] = useState(0);
      const counterRef = useRef(counter);
    ​
      const onAlertButtonClick = () => {
        setTimeout(() => {
          alert("Value: " + counterRef.current);
        }, 3000);
      };
    ​
      useEffect(() => {
        counterRef.current = counter;
      });
    ​
      return (
        <div>
          <p>You clicked {counter} times.</p>
          <button onClick={() => setCounter(counter + 1)}>Click me</button>
          <button onClick={onAlertButtonClick}>
            Show me the value in 3 seconds
          </button>
        </div>
      );
    };
    ​
    export default Counter;
    

    这时alert的是当前的值1。其实解决这个hooks的问题也可以参照类的instance。用useRef返回的immutable RefObject(current属性是可变的)来保存state,然后取值方式从counter变成了: counterRef.current 。
    二、没有生命周期
    比如我在开发中设置了个定时器,那我想页面销毁的时候肯定要清除定时器。那没有生命周期的hooks怎么实现我们的需求呢。

     //创建一个标识,通用容器
        const timer = useRef(null);
        const onEvent = async (eventName, params) => {
            switch (eventName) {
                case 'updateFileList':
                    try {
                        timer.current = setInterval(async () => {
                            await getReferenceBooKData(true, true, setAllocatedMainfestData);//某些循环请求数据的
                        }, 1500);
                    } catch (e) {
                        // todo
                    }
                    return;
               
            }
        }
        useEffect(() => () => { return componentWillUnmount() }, []);
        //销毁组件清除定时器
        const componentWillUnmount = ()=>{
            if (timer.current) {
                clearTimeout(timer.current);
            }
        };
    

    代码不是很全,主要可以参考方法的使用。就这样完美解决了我的问题,相当于监听了页面销毁的componentWillUnmount,如果你有其他需要周期需要操作的,也可以参考下面的用useEffect实现其他的周期变化操作

    useEffect( () => console.log("mount"), [] );
    useEffect( () => console.log("will update data1"), [ data1 ] );
    useEffect( () => console.log("will update any") );
    useEffect( () => () => console.log("will update data1 or unmount"), [ data1 ] );
    useEffect( () => () => console.log("unmount"), [] );
    
  • 相关阅读:
    properties,yml 文件读取 pom.xml 文件变量
    Docker实战编写Dockerfile
    在SpringBoot中实现异步事件驱动
    HttpClient封装工具类
    oracle临时表的两种方式
    关于cxGrid选中行操作关联数据集的一种方法
    安全释放 TreeView的DATA!
    行字段值拼接成字符串
    delphi中遍历枚举类型的方法
    C#将XML字符串转换成实体对象,并去除cdata
  • 原文地址:https://www.cnblogs.com/qianyy/p/13024157.html
Copyright © 2011-2022 走看看