ReactJS 教程

ReactJS - 主页 ReactJS - 简介 ReactJS - 路线图 ReactJS - 安装 ReactJS - 功能 ReactJS - 优势和缺点 ReactJS - 架构 ReactJS - 创建 React 应用程序 ReactJS - JSX ReactJS - 组件 ReactJS - 嵌套组件 ReactJS - 使用组件 ReactJS - 集合组件 ReactJS - 样式 ReactJS - 属性 (props) ReactJS - 使用属性创建组件 ReactJS - props 验证 ReactJS - 构造函数 ReactJS - 组件生命周期 ReactJS - 事件管理 ReactJS - 创建事件感知组件 ReactJS - Expense Manager 事件 ReactJS - 状态管理 ReactJS - 状态管理 API ReactJS - 无状态组件 ReactJS - Hooks 进行状态管理 ReactJS - Hooks 的组件生命周期 ReactJS - 布局组件 ReactJS - 分页 ReactJS - Material UI ReactJS - Http 客户端编程 ReactJS - 表单编程 ReactJS - 受控组件 ReactJS - 非受控组件 ReactJS - Formik ReactJS - 条件渲染 ReactJS - 列表 ReactJS - Key 键 ReactJS - 路由 ReactJS - Redux ReactJS - 动画 ReactJS - Bootstrap ReactJS - Map ReactJS - 表格 ReactJS - 使用 Flux 管理状态 ReactJS - 测试 ReactJS - CLI 命令 ReactJS - 构建和部署 ReactJS - 示例

Hooks

ReactJS - Hooks 简介 ReactJS - 使用 useState ReactJS - 使用 useEffect ReactJS - 使用 useContext ReactJS - 使用 useRef ReactJS - 使用 useReducer ReactJS - 使用 useCallback ReactJS - 使用 useMemo ReactJS - 自定义 Hooks

ReactJS 高级

ReactJS - 可访问性 ReactJS - 代码拆分 ReactJS - 上下文 ReactJS - 错误边界 ReactJS - 转发 Refs ReactJS - 片段 ReactJS - 高阶组件 ReactJS - 与其他库集成 ReactJS - 优化性能 ReactJS - Profiler API ReactJS - Portals ReactJS - 不使用 ES6 ECMAScript ReactJS - 不使用 JSX 的 React ReactJS - Reconciliation ReactJS - Refs 和 DOM ReactJS - 渲染道具 ReactJS - 静态类型检查 ReactJS - 严格模式 ReactJS - Web 组件

其他概念

ReactJS - 日期选择器 ReactJS - Helmet ReactJS - 内联样式 ReactJS - PropTypes ReactJS - BrowserRouter ReactJS - DOM ReactJS - 轮播 ReactJS - 图标 ReactJS - 表单组件 ReactJS - 参考 API

ReactJS 有用资源

ReactJS - 快速指南 ReactJS - 备忘录 Axios - 备忘录 ReactJS - 有用资源 ReactJS - 讨论


ReactJS - useCallback

useCallback Hooks(钩子)类似于 useMemo Hooks(钩子),提供记忆函数而不是值的功能。由于回调函数是 JavaScript 编程不可或缺的一部分,并且回调函数是通过引用传递的,因此 React 提供了一个单独的Hooks(钩子) useCallback 来记忆回调函数。理论上,useCallback 功能可以使用 useMemo Hooks(钩子)本身来实现。但是,useCallback 提高了 React 代码的可读性。

useCallback Hooks(钩子)的签名

useCallback Hooks(钩子)的签名如下 −

const <memoized_callback_fn> = useCallback(<callback_fn>, <dependency_array>);

此处,useCallback 接受两个输入并返回一个记忆化回调函数。输入参数如下 −

  • callback_fn − 要记忆的回调函数。

  • dependency_array − 保存回调函数所依赖的变量。

useCallback Hooks(钩子)的输出是 callback_fn 的记忆化回调函数。useCallback Hooks(钩子)的用法如下 −

const memoizedCallbackFn = useCallback(() => {
   // code
}, [a, b])

注意 − useCallback(callback_fn, dependency_array) 相当于 useMemo(() => callback_fn, dependency_array)。

应用 useCallback

让我们通过创建一个 React 应用程序来学习如何应用 useCallback Hooks(钩子)。

首先,使用 create-react-app 命令创建并启动一个 React 应用程序,如下所示 −

create-react-app myapp
cd myapp
npm start

接下来,在 components 文件夹下创建一个组件 PureListComponent (src/components/PureListComponent.js)

import React from "react";
function PureListComponent() {
   return <div>List</div>
}
export default PureListComponent

接下来,使用 PureListComponent 组件更新根组件,如下所示−

import PureListComponent from './components/PureListComponent';
function App() {
   return (
      <div style={{ padding: "5px" }}>
         <PureListComponent />
      </div>
   );
}
export default App;

接下来,打开 PureListComponent.js 并添加两个 props

  • 组件中要显示的项目列表

  • 回调函数,用于在控制台中显示用户单击的项目

import React from "react";
function PureListComponent(props) {
   const items = props['items'];
   const handleClick = props['handleClick']
   console.log("I am inside the PureListComponent")
   return (
      <div>
         {items.map((item, idx) =>
            <span key={idx} onClick={handleClick}>{item} </span>
         )}
      </div>
   )
}
export default React.memo(PureListComponent)

这里我们有,

  • 使用 items props 获取项目列表

  • 使用 handleClick 获取点击事件的处理程序

  • 使用 React.memo 包装组件以记忆组件。由于组件将为给定的一组输入呈现相同的输出,因此它在 react 中被称为 PureComponent。

接下来,让我们更新 App.js 并使用 PureListComponent,如下所示 −

import React, {useState, useEffect} from 'react';
import PureListComponent from './components/PureListComponent';
function App() {
   
   // 数字数组
   var listOfNumbers = [...Array(100).keys()];
   
   // 回调函数
   const handleCallbackFn = (e) => { console.log(e.target.innerText) }
   const [currentTime, setCurrentTime] = useState(new Date())
   useEffect(() => {
      let interval = setInterval(() => {
         setCurrentTime(new Date())
      }, 1000)
      return () => clearInterval(interval)
   }, [currentTime])
   return (
      <div style={ { padding: "5px" } }>
         <PureListComponent items={listOfNumbers} handleClick={handleCallbackFn}/>
         <div>Time: <b>{currentTime.toLocaleString().split(',')[1]}</b></div>
      </div>
   );
}
export default App;

这里我们包含了一个状态 currentTime,并使用 setInterval 每秒更新一次,以确保组件每秒重新渲染一次。

我们可能认为 PureListComponent 不会每秒重新渲染一次,因为它使用了 React.memo。但是,它会重新渲染,因为 props 值是引用类型。

接下来,更新根组件并使用 useMemouseCallback 来保存数组和回调函数,如下所示 −

import React, {useState, useEffect, useCallback, useMemo} from 'react';
import PureListComponent from './components/PureListComponent';
function App() {
   
   // 数字数组
   const listOfNumbers = useMemo(() => [...Array(100).keys()], []);
   
   // 回调函数
   const handleCallbackFn = useCallback((e) => console.log(e.target.innerText), [])
   const [currentTime, setCurrentTime] = useState(new Date())
   useEffect(() => {
      let interval = setInterval(() => {
         setCurrentTime(new Date())
      }, 1000)
      return () => clearInterval(interval)
   }, [currentTime])
   return (
      <div style={ { padding: "5px" } }>
         <PureListComponent items={listOfNumbers} handleClick={handleCallbackFn}/>
         <div>Time: <b>{currentTime.toLocaleString().split(',')[1]}</b></div>
      </div>
   );
}
export default App;

这里我们有,

  • 使用 useMemo 保存 items 数组

  • 使用 useCallback 保存 handleClick 回调函数

最后,在浏览器中检查应用程序,它不会每秒重新渲染 PureListComponent。

UseCallback Hook 的签名

useCallback 的用例

useCallback Hooks(钩子)的一些用例如下 −

  • 带有函数的纯函数组件props

  • useEffect 或其他具有函数依赖项的Hooks(钩子)

  • 在防抖动/节流或类似操作期间使用函数

优点

useCallback Hooks(钩子)的优点如下 −

  • 易于使用的 API

  • 易于理解

  • 提高应用程序的性能

缺点

从技术上讲,useCallback 没有缺点。但是,在应用程序中大量使用 useCallback 会带来以下缺点。

  • 降低应用程序的可读性

  • 降低应用程序的可理解性

  • 应用程序调试很复杂

  • 开发人员应该对 JavaScript 语言有深入的了解才能使用它

总结

useCallback 易于使用并可提高性能。同时,useCallback 应仅在绝对必要时使用。它不应该在每个场景中都使用。一般规则是检查应用程序的性能。如果需要改进,那么我们可以检查 useCallback 的使用是否有助于提高性能。如果我们得到积极的回应,那么我们可以使用它。否则,我们可以把改进和优化应用程序性能的工作交给 React。