码迷,mamicode.com
首页 > 其他好文 > 详细

react hooks的缺点(针对状态不同步和没有生命周期)

时间:2020-06-01 11:42:23      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:理解   创建   tab   console   async   alert   管理   解决   locate   

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"), [] );

react hooks的缺点(针对状态不同步和没有生命周期)

标签:理解   创建   tab   console   async   alert   管理   解决   locate   

原文地址:https://www.cnblogs.com/qianyy/p/13024157.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!