React Hooks的讲解与教程

这篇具有很好参考价值的文章主要介绍了React Hooks的讲解与教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是React Hooks

React Hooks 是 React 16.8 新增的一种特性,它可以让你在函数式组件中使用 state、生命周期、context 等 React 特性。Hooks 可以让你将复杂的逻辑拆分成多个独立可重用的函数,并且使得这些函数更加易于理解和测试。

Class组件存在的问题

  1. 复杂度高:类组件的定义和使用更加复杂繁琐。在类组件中,需要继承 React.Component 类,并且还要管理 this 指针、生命周期等,这使得代码变得冗长且难以理解。

  2. 嵌套层数过多:在传统 class 组件编写方式中,为了实现一些复杂逻辑或者 UI 界面,在不同生命周期函数中进行数据更新等操作容易导致代码嵌套层数过多、阅读性差,并且增加额外的复杂度和深度嵌套。

  3. 对功能模块封装比较困难:对于某个特定的功能模块或业务逻辑而言,在类组件内部如果想要将其封装成一个独立的方法或者函数,则往往需要定义私有属性或方法来实现封装。然而这样增加了代码耦合性并降低了可重用性。

  4. 不利于优化:由于 React 生命周期方法是按顺序执行的,因此在 componentDidMount 中做出昂贵计算可能会影响首次渲染时间。即使我们可以使用 shouldComponentUpdate 和 PureComponent 来减少重新渲染次数, 但仍然无法避免当 props 和 state 变化时带来的重新渲染。

React Hooks的优势?

React Hooks 的出现主要是为了解决 React Class组件的缺陷,并且让我们的函数组件也可以拥有类似于类组件的状态管理和副作用处理能力。

  1. 更简单的实现代码复用:在React Hooks出现之前,我们想要实现代码逻辑的复用需要使用到高阶组件、render props 等技术来帮助我们完成,但这样会增加额外的复杂度和深度嵌套,而 Hook 可以更轻松地实现代码逻辑的重用。

  2. 使代码逻辑更清晰:在传统的 class 组件编写方式中,在不同生命周期函数中进行数据更新时容易导致代码难以理解和维护。Hook 可以让你将相关业务逻辑放到同一个函数内部,从而提高可读性并减少了模块之间相互影响带来风险。

  3. 更便于大规模开发与测试:通过使用 Hook ,React 组件变成纯粹声明式渲染效果, 并且对应该渲染结果只由 Props 和 State 决定, 这种特点使得 React 开发者倾向于采取函数式编程(Functional Programming)范例去建立 UI.

  4. 更加灵活和自由 :Hooks 提供了很多新特性例如 state、useEffect、useContext 等,使得函数组件拥有了更多的功能和使用场景,并且可以自由地将这些 Hook 组合在一起以实现各种需求。

Hook的出现,可以解决我们Class组件存在的这些问题,它可以让我们在不编写class的情况下使用state以及其他的React特性。

注意:Hook只能在函数组件中使用,不能在类组件,或者函数组件之外的地方使用

Class组件和Functional组件对比

React Hooks的讲解与教程

State Hook的API

useState

作用

useState,它可以帮助我们在函数式组件中管理状态。

语法

const [state, setState] = useState(initialState);
  • state: 表示当前的状态值。
  • setState: 是一个更新 state 值的函数,调用该函数会重新渲染组件并更新状态。

参数

  • initialState: 表示 state 的初始值。可以是任何的类型,例如数字、字符串、数组或对象等。

返回值

  • 数组:包含两个元素 [state, setState]

使用方法

定义了一个计数器组件,使用了 useState 来初始化 count 状态,并且通过 setCount 函数来更新 count 状态。当用户点击 Increment 按钮时,就会触发 increment 函数并将 count 增加一次。在此过程中,React 自动检测到状态变化,并重新渲染页面以显示最新结果。

import React, { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  function increment() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

export default Counter;

Effect

作用

useEffect 它可以让我们在函数式组件中执行副作用操作(例如:从服务器获取数据、手动更新 DOM 等)。

语法

useEffect(effect, dependencies);
  • effect:表示要执行的副作用函数。
  • dependencies:表示 useEffect 需要监测变化的依赖项数组。

参数

  • effect: 副作用函数。该函数会在每次渲染时都被调用,并且可以根据需要返回清理函数。如果不需要清理,则应该返回 undefined 或者空函数。
  • dependencies: 可选参数,传入一个数组来指定监测哪些状态/属性变化而触发副作用操作。

返回值

无返回值。

使用方法

import React, { useState, useEffect } from "react";
import axios from "axios";

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const result = await axios("https://jsonplaceholder.typicode.com/posts");
      setData(result.data);
    }
    fetchData();
  }, []);

  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {data.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

在上面的代码示例中我们定义了一个简单的应用程序,我们使用了 useState 来初始化 data 状态,并且在 useEffect 中使用 axios 库从服务器获取数据。当数据加载完成时,我们使用 setData 函数更新 data 状态,并且通过 map 方法将每个帖子的标题显示为列表项。在此过程中,React 自动检测到状态变化,并重新渲染页面以显示最新结果。

useContext

作用

useContext 它可以让我们在组件树中跨层级传递数据,避免了繁琐的 props 传递。

用法

首先,我们需要创建一个 Context 对象来存储要共享的数据:

// MyContext.js

import React from "react";

const MyContext = React.createContext();

export default MyContext;

然后,在父组件中设置共享数据,并将其作为 value 属性传递给 Context.Provider 组件:

// App.js

import React, { useState } from "react";
import MyContext from "./MyContext";
import ChildComponent from "./ChildComponent";

function App() {
  const [name, setName] = useState("John");

  return (
    <div>
      <h1>Hello, {name}!</h1>
      <MyContext.Provider value={name}>
        <ChildComponent />
      </MyContext.Provider>
    </div>
  );
}

export default App;

这里我们使用了 useState 来定义状态变量 name 和用于更新该变量的函数 setName。然后将其作为值传递给 Context。

接下来,在子组件中使用 useContext Hook 来获取共享数据并进行展示:

// ChildComponent.js

import React, { useContext } from "react";
import MyContexct from "./MyContexct";

function ChildComponent() {
  const name = useContext(MyContexct);

  return (
    <div>
      <h2>Child Component</h2>
      <p>{name}, how are you doing?</p>
    </div>
  );
}

export default ChildComponent;

如上述代码所示,我们可以通过 useContext Hook 来获取 Context 中的共享数据,并将其命名为 name。然后在组件中展示该数据。

最终,当我们运行这个应用程序时,它将显示一个包含 "Hello, John!""John, how are you doing?" 的页面。

注意:到子组件无需通过 props 获取父组件的状态变量值即可访问该值。

useReducer

作用

useReducer 它可以帮助我们使用 reducer 函数管理复杂的组件状态。

用法

首先,我们需要定义一个 reducer 函数来管理组件状态。该函数接收两个参数:当前状态(state)和更新该状态所需的操作(action)。然后根据 action 的类型进行相应的处理并返回新的 state。

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    case "DECREMENT":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

在上面的代码中,我们创建了一个名为 reducer 的函数,并根据传入的不同类型执行相应操作来更新组件状态。

接下来,在父组件中使用 useReducer Hook 来初始化和获取共享数据以及 dispatch 方法:

import React, { useReducer } from "react";
import reducer from "./reducer";

function App() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  function increment() {
    dispatch({ type: "INCREMENT" });
  }

  function decrement() {
    dispatch({ type: "DECREMENT" });
  }

  return (
    <div>
      <h2>Count:{state.count}</h2>
        <button onClick={increment}>Increment</button>
        <button onClick={decrement}>Decrement</button>
     </div>
   );
}

export default App;

如上述代码所示,通过调用 useReducer Hook,我们可以获取到当前的状态(state)和 dispatch 方法。其中第一个参数是 reducer 函数,第二个参数是初始状态值。在这里我们使用了 { count: 0 } 作为初始 state 值。

然后在父组件中定义两个函数:increment 和 decrement,它们分别调用 dispatch({ type: "INCREMENT" })dispatch({ type: "DECREMENT" }) 来更新共享数据。

最终,在返回的 JSX 中展示当前计数器的值并添加增加/减少按钮来触发对应操作即可。

useCallback

作用

useCallback 它可以帮助我们优化性能并避免不必要的重新渲染。

用法

首先,我们需要理解什么是函数记忆。在 JavaScript 中,如果两个相同参数值之间存在对应关系,则称这些函数有“记忆”。因此,在进行计算时使用已经计算过的结果而不是再次运行该函数以提高效率。

接下来,请看如下代码示例:

import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  function handleClick() {
    console.log("Clicked!");
    setCount(count + 1);
  }

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={handleClick}>Increment</button>
    </div>
   );
}

export default App;

上面的代码中展示了一个简单的计数器组件,并且定义了一个名为 handleClick 的事件处理程序方法。当点击按钮时,会触发该方法并更新内部状态以反映当前值。

然而,在每次渲染组件时都会创建新的 handleClick 方法实例可能会导致一定程度上的性能问题。这就是为什么我们需要使用 useCallback 来进行优化。

使用 useCallback 来改写后:

import React, { useState, useCallback } from "react";

function App() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log("Clicked!");
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={handleClick}>Increment</button>
    </div>
   );
}

export default App;

在上面的代码中,我们使用了 useCallback 来缓存 handleClick 方法并根据需要更新它。这样,在组件重新渲染时就不会创建新的实例,从而避免了性能问题。

注意:第二个参数 [count] 是依赖项数组。如果该值发生变化,则会触发回调函数的重新计算和更新处理程序方法。

useMemo

作用

useMemo ,它可以帮助我们优化性能并避免不必要的重新计算。

用法

首先,我们需要理解什么是记忆。在 JavaScript 中,如果两个相同参数值之间存在对应关系,则称这些函数有“记忆”。因此,在进行计算时使用已经计算过的结果而不是再次运行该函数以提高效率。

import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
  }

  const result = fibonacci(count);

  return (
    <div>
      <h2>Result: {result}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
   );
}

export default App;

上面的代码中展示了一个简单的斐波那契数列组件,并且定义了一个名为 fibonacci 的递归方法。每当用户点击按钮时都会调用该方法以更新内部状态以反映当前值。

然而,在每次渲染组件时都会重新计算斐波那契数列可能会导致一定程度上的性能问题。这就是为什么我们需要使用 useMemo 来进行优化。

改写后如下所示:

import React, { useState, useMemo } from "react";

function App() {
  const [count, setCount] = useState(0);

  function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
  }

  const result = useMemo(() => fibonacci(count), [count]);

  return (
    <div>
      <h2>Result: {result}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
   );
}

export default App;

在上面的代码中,我们使用了 useMemo 来缓存斐波那契数列计算结果并根据需要更新它。这样,在组件重新渲染时就不会重新计算该值,从而避免了性能问题。

注意:第二个参数 [count] 是依赖项数组。如果该值发生变化,则会触发回调函数的重新计算和更新处理程序方法。

useRef

作用

useRef 它可以帮助我们在函数组件中保存可变值,并且不会导致组件重新渲染。

用法

import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  function handleAlertClick() {
    setTimeout(() => {
      alert(`You clicked ${count} times`);
    }, 3000);
  }

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={handleAlertClick}>Show Alert</button>
    </div>
   );
}

export default App;

上面的代码中展示了一个简单的计数器组件,并且定义了一个名为 handleAlertClick 的事件处理程序方法。当用户点击“Show Alert”按钮时,该方法会等待三秒钟然后显示警告框以反映当前值。

然而,在该三秒钟内如果用户再次点击“Increment”按钮,则计数器将增加并且警告框仍将显示旧的值。这就是因为每次重新渲染组件时都创建了新的 count 变量实例。

改写后如下所示:

import React, { useState, useRef } from "react";

function App() {
  const [count, setCount] = useState(0);
  
  const countRef = useRef(count);

  function handleAlertClick() {
    setTimeout(() => {
      alert(`You clicked ${countRef.current} times`);
    }, 3000);
  }

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={handleAlertClick}>Show Alert</button>
    </div>
   );
}

export default App;

在上面的代码中,我们使用了 useRef 来保存可变值,并且不会导致组件重新渲染。这样,在每次重新渲染时都可以访问到最新的计数器值。

注意:需要将初始值传递给 useRef,并通过 .current 属性来读写该值。文章来源地址https://www.toymoban.com/news/detail-512873.html

到了这里,关于React Hooks的讲解与教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React Hooks ——性能优化Hooks

    Hooks从语法上来说是一些函数。这些函数可以用于在函数组件中引入状态管理和生命周期方法。 简洁 从语法上来说,写的代码少了 上手非常简单 基于函数式编程理念,只需要掌握一些JavaScript基础知识 与生命周期相关的知识不用学,react Hooks使用全新的理念来管理组件的运作

    2024年02月06日
    浏览(44)
  • React的hooks---自定义hooks

    通过自定义 Hook,可以将组件逻辑提取到可重用的函数中,在 Hook 特性之前,React 中有两种流行的方式来共享组件之间的状态逻辑: render props 和 高阶组件 ,但此类解决方案会导致组件树的层级冗余等问题。而自定义 Hook 的使用可以很好的解决此类问题 自定义 Hook 是一个函数

    2024年02月15日
    浏览(32)
  • 【React】React Hooks解析

    React 16.8 + 为什么需要Hook? Hook是 React 16.8 的新增特性,它可以让我们在不编写class的情况下使用state以及其他的React特性(比如生命周期) 我们先来思考一下class组件相对于函数式组件有什么优势?比较常见的是下面的优势: class组件可以 定义自己的state ,用来 保存组件自己内

    2024年02月11日
    浏览(55)
  • React Hooks 基本使用

    class 组件如果业务复杂,很难拆分和重构,很难测试;相同业务逻辑分散到各个方法中,逻辑混乱 逻辑复用像 HOC 、 Render Props ,不易理解,学习成本高 React 提倡函数式编程,函数更易拆分,更易测试 但是函数组件太简单,为了增强函数组件的功能,媲美 class 组件: 函数组

    2024年01月21日
    浏览(41)
  • react hooks

    功能:让函数组件也可以有state状态, 并进行状态数据的读写操作 语法:const [xxx, setXxx] = React.useState(initValue) 参数: 第一次初始化指定的值在内部作缓存 返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数 setXxx()2种写法: setXxx(newValue): 参数为非函数

    2024年02月05日
    浏览(41)
  • React hooks 大全详情

    hook 是react 16.8的新增特性 ,他可以让你不在编写class的情况下shiystate以及react的特性 Hooks的出现,首先解决了以下问题: 告别了令人疑惑的生命周期 告别类组件中烦人的this 告别繁重的类组件,回归到了熟悉的函数组件 react 整个思想上面的转变,从“面向对象”的思想转为“

    2024年02月08日
    浏览(47)
  • React学习8 hooks

    1、setState setState更新数据是异步的,如果想获取更新完的数据,需要通过第二个参数回调函数来获取 2、lazyLoad,用的时候再调用,不会预先调用,需要用suspence包裹注册路由 3、stateHook userState 函数组件中使用state,通过调用React.useState()使用,该数组两个变量,第一个存储状态

    2024年02月08日
    浏览(37)
  • React hooks源码阅读

    一、版本 react:17.0.2 react-dom: 17.0.2 二、代码仓库 react源码的管理方式是monorepo模式,它把react中相对独立的模块分割出来作为一个软件包(例如:react包、react-dom包、react-server包等等),将所有软件包统一放置在/packages中,这样一个react代码仓库就包含了所有的react模块。源码

    2024年02月04日
    浏览(32)
  • React Hooks 实战案例

    React Hooks 是 React 16.8 版本引入的新特性,它使得在函数组件中也能够使用状态(state)和其他 React 特性。 在 React 之前的版本中,组件要么是函数组件,要么是类组件。函数组件可以使用纯函数的方式编写,但是没有状态(state)和其他 React 特性;类组件则可以拥有状态和其

    2024年02月08日
    浏览(44)
  • React Hooks解析

    1. react使用hook的意义 Hook 是 React 16.8 的新增特性,它可以让我们在不编写class的情况下使用state以及其他的React特性(比如生命周期)。 class组件与函数式组件: class组件可以 定义自己的state ,用来 保存组件自己内部的状态, 函数式组件不可以,因为函数每次调用都会产生新

    2024年02月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包