• 关于useEvent以及它解决了什么问题


    useCallback闭包与setState更新矛盾

    useCallback的函数fn,使用的state, 是闭包中的state
    如果每次render要拿到最新的stata, 就要将state放在依赖数组上,否则读取的总是闭包中的state, 而不是最新的state

    但是这样一来, 就因为新增了useCallback的依赖,失去了useCallback缓存fn,保持fn引用不变的初衷

    export default function App() {
      const [counter, setCounter] = useState(0);
    
      const handleClick = useCallback(() => {
        console.log(counter);
        setCounter(counter => counter + 1);
      }, []);
    
      return (
        <div onClick={handleClick}>
          click to add counter
          counter: {counter}
        </div>
      )
    }
    

    因此引入useEvent, 主要基于ref+useCallback实现useEvent来解决这个问题

    // (!) 近似行为
    function useEvent(handler) {
      const handlerRef = useRef(null);
    
      // 每次render都在ref中维持一个最新的handler引用,从而拿到最新的上下文环境以及状态。在实际实现时它会在 layout effect 之前执行
      useLayoutEffect(()=>{
         handlerRef.current = handler;
      })
      
      // 返回一个useCallback包裹的依赖数组长度为0的函数,在useCallback的缓存函数里调用handler
      // 使得handler执行时是最新的上下文环境与状态,绕过了闭包陷阱,去掉了多余的deps,同时保证了onClick引用不变
      return useCallback((...args) => {
        const fn = handlerRef.current;
        return fn(...args);
      }, []);
    }
    
    function Chat() {
      const [text, setText] = useState('');
    
      // ✅ Always the same function (even if `text` changes)
      const onClick = useEvent(() => {
        sendMessage(text);
      });
    
      return <SendButton onClick={onClick} />;
    }
    
  • 相关阅读:
    Condition控制线程通信
    Lock同步锁
    通过Callable接口创建线程
    CountDownLatch闭锁
    CopyOnWriteArrayList笔记
    原子变量与CAS算法
    Java网络编程之UDP
    Java网络编程之Socket
    Java网络编程之URLConnection
    Java中处理异常中return关键字
  • 原文地址:https://www.cnblogs.com/ltfxy/p/16458845.html
Copyright © 2020-2023  润新知