React.js学习-使用内置hook

2020-09-07 10:48:542022-05-11 22:19:50

什么是 hook

组件自身能够通过某种机制再触发状态的变更并且引起re-render,而这种“机制”就是 Hooks!

useEffect

  • 默认情况下,它在第一次渲染之后和每次更新之后都会执行。React 确保了每次运行effect的同时,DOM 都已经更新完毕

  • 每次重新渲染,都会生成新的effect,替换掉之前的。某种意义上讲,effect更像是渲染结果的一部分 —— 每个effect “属于”一次特定的渲染。

  • 每个effect都可以返回一个清除函数。如此可以将添加和移除订阅的逻辑放在一起。他们都属于effect的一部分

自定义 hook 的 state 是否共享

在两个组件中使用相同的hook不会共享state,自定义hook是一种重用状态逻辑的机制,所以每次使用自定义hook时其中的所有state和副作用是完全隔离的

hook 原理

初次渲染的时候,按照 useState,useEffect 等 hook 的顺序,把 state,deps 等按顺序塞到 memoizedState 数组中。

更新的时候,按照顺序,从 memoizedState 中把上次记录的值拿出来。

state 和 useState 的对应关系

Reacthook的调用顺序来知道stateuseState的对应关系,所以不能在条件/循环中调用hook

useEffect 的执行时机

useEffect会在浏览器绘制后延迟执行,但会保证在任何新的渲染前执行

useCallback 和 useMemo

useCallback(fn, deps) == useMemo(() => fn(), deps);

使用过多 hook 后性能问题

hook 不会因为在渲染时创建函数而变慢,在现代浏览器中闭包和类的原始性能只有在极端场景下才会有明显的差别

useState 惰性求值

如果初始化state需要通过复杂计算获得,那么可以传入一个函数,在函数中计算并返回初始的state,此函数只在初始渲染时被调用

const [count, setCount] = useState(() => calState());

hook 使用必须要遵循的规则

在函数值组件主体内(指 React 渲染阶段)改变DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性。使用useEffect完成副作用操作赋值给useEffect的函数会在组件渲染到屏幕后执行。

useRef

通过useRef来拥有一个在所有帧共享的变量

useReducer

  • state 逻辑较复杂且包含多个子值

  • 下一个 state 依赖于之前的 state

useImperativeHandle

简单来讲: useImperativeHandle 赋予函数式组件使用 ref 的特权, 通常和 forwardRef 成对出现,

使用方式:

const { useImperativeHandle, forwardRef, useRef } = React;

const Modal = forwardRef((props, ref) => {
  const open = () => {
    console.log("open");
  };
  useImperativeHandle(ref, () => ({
    open,
  }));

  return <span>modal</span>;
});

const App = () => {
  const modalRef = useRef(null);

  return (
    <div>
      <Modal ref={modalRef} />
      <button onClick={() => modalRef.current.open()}>click me</button>
    </div>
  );
};

const root = ReactDOM.createRoot(document.querySelector("#app"));
root.render(<App />);