React 笔记--HOOK

动机

在组件之间复用状态逻辑很难

如果你使用过 React 一段时间,你也许会熟悉一些解决此类问题的方案,比如 render props 和 高阶组件。但是这类方案需要重新组织你的组件结构,这可能会很麻烦,使你的代码难以理解。
Hook 使你在无需修改组件结构的情况下复用状态逻辑。具体是自定义 Hook

复杂组件变得难以理解

为了解决这个问题,Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分。你还可以使用 reducer 来管理组件的内部状态,使其更加可预测。

难以理解的 class

概览

什么是 Hook

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。

自定义 Hook

如果函数的名字以 “use” 开头并调用其他 Hook,我们就说这是一个自定义 Hook。

跳过渲染

需要注意的是,React 可能仍需要在跳过渲染前再次渲染该组件。不过由于 React 不会对组件树的“深层”节点进行不必要的渲染,所以大可不必担心。如果你在渲染期间执行了高开销的计算,则可以使用 useMemo 来进行优化。

Hook API

useState

  1. 与 class 组件中的 setState 方法不同,useState 不会自动合并更新对象。你可以用函数式的 setState 结合展开运算符来达到合并更新对象的效果。
  2. React 会确保 setState 函数的标识是稳定的,并且不会在组件重新渲染时发生变化。这就是为什么可以安全地从 useEffect 或 useCallback 的依赖列表中省略 setState。

useEffect

我们推荐启用 eslint-plugin-react-hooks 中的 exhaustive-deps 规则。此规则会在添加错误依赖时发出警告并给出修复建议

effect 的执行时机

useEffect 的函数会在浏览器完成布局与绘制之后,在一个延迟事件中被调用。

从 React 18 开始,当它是离散的用户输入(如点击)的结果时,或者当它是由 flushSync 包装的更新结果时,传递给 useEffect 的函数将在屏幕布局和绘制之前同步执行。这种行为便于事件系统或 flushSync 的调用者观察该效果的结果。

这只影响传递给 useEffect 的函数被调用时 — 在这些 effect 中执行的更新仍会被推迟。这与 useLayoutEffect 不同,后者会立即启动该函数并处理其中的更新。

即使在 useEffect 被推迟到浏览器绘制之后的情况下,它也能保证在任何新的渲染前启动。React 在开始新的更新前,总会先刷新之前的渲染的 effect。

依赖项数组不会作为参数传给 effect 函数。虽然从概念上来说它表现为:所有 effect 函数中引用的值都应该出现在依赖项数组中。未来编译器会更加智能,届时自动创建数组将成为可能。

useContext

调用了 useContext 的组件总会在 context 值变化时重新渲染。如果重渲染组件的开销较大,你可以 通过使用 memoization 来优化。

useMemo

记住,传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行不应该在渲染期间内执行的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo。

你可以把 useMemo 作为性能优化的手段,但不要把它当成语义上的保证。

useDeferredValue

注意与 防抖和节流 的区别

Hook 规则

  1. 只在最顶层使用 Hook
  2. 只在 React 函数中调用 Hook

ESLint 插件

eslint-plugin-react-hooks

有类似 forceUpdate 的东西吗

  const [ignored, forceUpdate] = useReducer(x => x + 1, 0);

  function handleClick() {
    forceUpdate();
  }

可能的话尽量避免这种模式。

如何测量 DOM 节点

function MeasureExample() {
  const [height, setHeight] = useState(0);

  const measuredRef = useCallback(node => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);
    }
  }, []);

  return (
    <>
      <h1 ref={measuredRef}>Hello, world</h1>
      <h2>The above header is {Math.round(height)}px tall</h2>
    </>
  );
}

在这个案例中,我们没有选择使用 useRef,因为当 ref 是一个对象时它并不会把当前 ref 的值的 变化 通知到我们。使用 callback ref 可以确保 即便子组件延迟显示被测量的节点 (比如为了响应一次点击),我们依然能够在父组件接收到相关的信息,以便更新测量结果。

避免向下传递回调

向下传递 dispatch 是处理深度更新的推荐模式。

const TodosDispatch = React.createContext(null);

function TodosApp() {
  // 提示:`dispatch` 不会在重新渲染之间变化
  const [todos, dispatch] = useReducer(todosReducer);

  return (
    <TodosDispatch.Provider value={dispatch}>
      <DeepTree todos={todos} />
    </TodosDispatch.Provider>
  );
}
React 18是React的最新版本,它引入了一些新的功能和改进。在学习React 18时,你可以关注以下几个方面: 1. React组件:React组件是构建用户界面的基本单元。你可以使用React.createElement()函数或JSX语法来创建React元素和组件。React元素是不可变的,而React组件是可复用的。\[1\] 2. react-dom.development.jsreact-dom/client模块:这些模块提供了处理真实DOM的功能,包括Diff算法和渲染成真实DOM的过程。你可以在HTML文件中引入这些模块,并使用ReactDOM.createRoot()方法来渲染React的DOM。\[2\] 3. HookHookReact中的特殊函数,它允许你在函数组件中添加状态和其他特性。例如,useState是一个Hook,它可以让你在函数组件中添加状态。你可以使用useState来定义和更新状态,并在组件中使用它们。\[3\] 在学习React 18时,你可以通过阅读官方文档、参考教程和实践项目来深入了解这些概念和用法。同时,你也可以与其他开发者交流和分享经验,加深对React的理解。 #### 引用[.reference_title] - *1* *2* *3* [2023年React18笔记【慕课网imooc】【尚硅谷】【Vue3+React18 + TS4考勤系统】](https://blog.csdn.net/qq_28838891/article/details/124598439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值