React常用Hooks

原文合集地址如下,有需要的朋友可以关注

本文地址

合集地址

React 提供了许多常用的 Hooks,用于在函数组件中添加状态管理、副作用处理和其他功能,下面介绍其中几个常用的,React还有很多其他hooks。

useState:

useSate用于在函数组件中添加状态管理。它返回一个状态值和更新该状态值的函数。 使用时一些特点和注意事项

  1. 正确定义初始状态:在使用 useState 时,需要为初始状态提供一个合适的值。确保初始状态的类型与后续状态的类型保持一致,避免出现类型错误。
  2. 解构数组:useState 返回一个包含状态值和更新状态值的函数的数组,通常可以使用数组解构来获取它们。例如:const [state, setState] = useState(initialState);。这样做可以提高代码的可读性。
  3. 更新状态:使用 setState 函数来更新状态值。注意,setState 并不会像类组件中的 setState 方法一样自动合并更新,而是替换整个状态对象。因此,在更新状态时,请确保包含了所有需要保留的状态值,而不仅仅是更新的部分。
  4. 异步更新:由于状态更新是异步的,多次连续调用 setState 不会立即反映到状态值上。如果需要基于先前的状态进行更新,可以使用回调函数的形式调用 setState。例如:setState(prevState => prevState + 1);
  5. 函数式更新:当新的状态值依赖于先前的状态值时,可以使用函数式更新形式。这样可以避免依赖于当前状态的值,并确保获取到最新的状态。例如:setState(prevState => prevState + 1);
import { Button } from 'antd';
import React, { useState } from 'react';

const Test = (props: any) => {
    const [count, setCount] = useState(0);

    const onChange = () => {
        setCount(count + 1);
        // 异步更新有时候会不生效,需要这样写
        setCount(pre => pre + 1);
    }
    return (
        <div>
            {count}
            <Button onClick={onChange}>点击</Button>
        </div>
    )
}
export default Test;

useEffect

用于处理副作用,例如数据获取、订阅、事件处理等。它在组件渲染完成后执行,并可以在组件更新时重新执行。 useEffect 是 React 中常用的 Hook 之一,用于处理副作用操作,例如数据获取、订阅、事件监听等。useEffect 在组件渲染后执行,并可以在组件更新时重新执行。

useEffect 接受两个参数:一个副作用函数和一个依赖项数组。

副作用函数是在组件渲染后执行的函数。它可以包含任何副作用操作,例如订阅事件、发送网络请求、操作 DOM 等。该函数可以返回一个清理函数,用于在组件卸载或重新渲染之前执行清理操作。

依赖项数组是一个可选的参数,用于指定副作用函数依赖的值。当依赖项数组发生变化时,useEffect 将重新执行副作用函数。如果不提供依赖项数组,副作用函数将在每次组件更新时都执行。如果传入一个空数组 [],副作用函数将只在组件首次渲染后执行,不会重新执行。

以下是 useEffect 的基本用法:

import { useEffect } from 'react';

function MyComponent() {
// 无依赖项,会一值执行
 useEffect(() => {
  // 操作
   
  });
// 依赖项为空,组件初始化会执行一次
useEffect(() => {
  // 操作
   
  },[]);
  // 依赖于某个变量或函数,在依赖项发生变化后触发
  useEffect(() => {
    // 在组件渲染后执行副作用操作

    // 返回一个清理函数(可选)
    return () => {
     // 在组件卸载或重新渲染之前执行清理操作
    //该清理函数将在组件卸载或重新渲染之前执行
    };
  }, [/* 依赖项数组 */]);


  return (
   <div></div>
  );
}

下面是一些关于 useEffect 的常见用法和注意事项:

  1. 数据获取和订阅:可以在 useEffect 中进行异步操作,例如发起网络请求获取数据或订阅事件。确保在清理函数中取消订阅或中断请求,以避免内存泄漏。
  2. 依赖项数组的使用:通过依赖项数组,可以控制副作用函数的执行时机。只有当依赖项发生变化时,才会重新执行副作用函数。如果不提供依赖项数组,则副作用函数将在每次组件更新时都执行。
  3. 空依赖项数组的使用:如果副作用函数不依赖任何状态或属性,可以传入一个空数组 [],使副作用函数仅在组件首次渲染后执行一次。
  4. 清理函数的使用:如果副作用函数需要进行清理操作,例如取消订阅或清除定时器,请在副作用函数中返回一个清理函数。该清理函数将在组件卸载或重新渲染之前执行。
  5. 异步操作和更新状态:在副作用函数中进行异步操作时,确保正确处理状态的更新。使用函数式更新或通过依赖项数组传入更新的状态。

useContext

当使用 useContext Hook 时,可以方便地在 React 组件中访问全局的上下文数据。下面是一个使用 useContext 的简单例子:

首先,创建一个上下文对象:

import React, { createContext } from 'react';

// 创建上下文对象
const MyContext = createContext();

// 上下文提供器
function MyContextProvider({ children }) {
  const sharedData = 'Shared Data';

  return (
    <MyContext.Provider value={sharedData}>
      {children}
    </MyContext.Provider>
  );
}

在上面的例子中,创建了一个名为 MyContext 的上下文对象,并通过 MyContext.Provider 提供器将共享数据 sharedData 传递给子组件。

然后,在需要访问上下文数据的组件中使用 useContext

import React, { useContext } from 'react';

function MyComponent() {
  const sharedData = useContext(MyContext);

  return (
    <div>
      Shared Data: {sharedData}
    </div>
  );
}

使用 useContext Hook 来获取 MyContext 上下文的值,并将其赋值给 sharedData 变量。然后,可以在组件中使用该值进行渲染或其他操作。

注意事项:

  1. 使用 useContext 前,确保已在组件树中的某个地方提供了上下文。在上面的例子中,通过 MyContext.Provider 提供器在组件树中提供了上下文数据。
  2. 上下文数据的更新:当上下文数据发生变化时,使用 useContext 的组件会自动重新渲染。这意味着,当共享数据发生更改时,使用该上下文的所有组件都会更新。
  3. 上下文嵌套:React 允许上下文进行嵌套。在嵌套的情况下,使用 useContext 会获取最接近的上层提供器的值。
  4. 上下文的性能优化:当上下文数据较大或频繁变化时,可以使用 React.memouseMemo 或自定义的优化方法来优化上下文的性能。
  5. 避免过度使用上下文:上下文是用于共享数据的有用工具,但过度使用可能导致组件之间的耦合性增加。请在需要共享数据的组件之间仔细考虑使用上下文的合适程度。

使用 useContext 可以方便地访问和共享上下文数据,但请确保在使用前提供了上下文,并注意上述的注意事项,以确保正确使用上下文功能。

useReducer

useReducer 是 React 中的一个常用 Hook,用于管理具有复杂状态逻辑的组件。它类似于 Redux 中的 reducer,接收一个状态和操作函数,并返回新的状态和派发操作的函数。

使用 useReducer 时,需要定义一个 reducer 函数和初始状态。

reducer 函数接收当前状态和一个操作(action),并根据操作的类型来更新状态。它返回更新后的状态。reducer 函数的定义类似于 Redux 中的 reducer:

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

初始状态是状态的初始值:

const initialState = { count: 0 };

然后,使用 useReducer Hook 在组件中应用 reducer:

import React, { useReducer } from 'react';

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
}

在上述例子中,我们使用 useReducer 定义了状态 state 和派发操作的函数 dispatch。我们可以根据操作的类型通过调用 dispatch 函数来派发操作,并由 reducer 函数来更新状态。

useReducer 在处理具有复杂状态逻辑的组件时非常有用。以下是一些使用场景:

  • 计数器:可以使用 useReducer 来管理计数器的状态和操作,例如增加、减少计数等。
  • 表单处理:使用 useReducer 可以更好地管理表单的状态和用户输入的操作,以及进行表单验证等复杂逻辑。
  • 数据列表:当处理复杂的数据列表时,使用 useReducer 可以更好地管理数据的加载、筛选、排序等操作,以及处理分页等功能。

总的来说,useReducer 适用于需要管理复杂状态逻辑的组件,并且可以帮助组织和更新状态,以及处理相关的操作。它可以代替使用 useState 的方式,特别适合管理具有多个操作类型和相关状态的组件。

useMemo

useMemo 是 React 中的一个常用 Hook,用于在组件渲染过程中进行性能优化,避免不必要的计算和重复渲染。

useMemo 接受两个参数:一个计算函数和依赖项数组。它会在组件渲染过程中执行计算函数,并将计算结果缓存起来。只有当依赖项数组中的值发生变化时,才会重新执行计算函数。

使用 useMemo 可以避免在每次渲染时重复计算耗时的操作,并且可以根据依赖项的变化来更新计算结果。以下是一些 useMemo 的常见使用场景:

  1. 计算结果的缓存:当需要根据某些输入计算结果时,可以使用 useMemo 缓存计算结果,避免重复计算。这在计算量较大的场景下特别有用。
  2. 避免不必要的重渲染:当一个组件依赖于某个状态或属性,但这些状态或属性的变化并不会影响到组件的渲染结果时,可以使用 useMemo 来缓存渲染结果,避免不必要的重渲染。
  3. 优化子组件的渲染:当将一个计算结果作为属性传递给子组件时,可以使用 useMemo 缓存计算结果,以避免在每次父组件渲染时都重新计算并传递给子组件。
  4. 性能敏感的比较操作:当需要进行一些性能敏感的比较操作,例如深度比较对象或数组时,可以使用 useMemo 缓存比较结果,以避免在每次渲染时重新执行比较操作。 下面是一个使用 useMemo 的简单例子,展示如何缓存计算结果以提高性能:
import React, { useMemo, useState } from 'react';

function ExpensiveComponent() {
  // 假设这里有一个计算耗时的函数
  function calculateExpensiveValue() {
    // ... 复杂的计算逻辑 ...
    console.log('Calculating expensive value...');
    return Math.random();
  }

  // 使用 useMemo 缓存计算结果
  const expensiveValue = useMemo(() => calculateExpensiveValue(), []);

  return (
    <div>
      Expensive Value: {expensiveValue}
    </div>
  );
}

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

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <ExpensiveComponent />
    </div>
  );
}

在上述代码中,有一个 ExpensiveComponent 组件,其中包含一个计算耗时的函数 calculateExpensiveValue。为了避免在每次渲染时都重新计算 expensiveValue,使用 useMemo 缓存计算结果。

通过将 calculateExpensiveValue 函数作为 useMemo 的第一个参数,并将空数组作为依赖项传递给 useMemo,确保只在组件首次渲染时执行一次计算,并将结果缓存起来。当 count 发生变化时,ExpensiveComponent 重新渲染,但不会触发计算函数的重新执行。

useLayoutEffect

useLayoutEffect 是 React 中的一个 Hook,与 useEffect 类似,但它在 DOM 变更之后同步执行,而不是在浏览器绘制之后执行。它会在浏览器布局和绘制之前同步执行回调函数。

使用 useLayoutEffect 可以在浏览器布局完成后立即执行一些操作,以确保获取到最新的 DOM 布局信息,并在下一次渲染之前同步地更新 UI。这在需要准确地测量 DOM 元素的尺寸、位置或进行 DOM 操作时非常有用。

下面是一个使用 useLayoutEffect 的简单例子:

import React, { useRef, useLayoutEffect } from 'react';

function MeasureElement() {
  const ref = useRef();

  useLayoutEffect(() => {
    // 在浏览器布局完成后立即执行操作
    const element = ref.current;
    const { width, height } = element.getBoundingClientRect();

    // 使用测量结果进行操作
    console.log('Element size:', width, height);
  }, []);

  return <div ref={ref}>Measure me!</div>;
}

function App() {
  return (
    <div>
      <MeasureElement />
    </div>
  );
}

在上述例子中,创建了一个名为 MeasureElement 的组件,在组件内部使用了 useLayoutEffect。在 useLayoutEffect 的回调函数中,我们可以获取到被测量元素的最新布局信息,并进行相应的操作。

在这个例子中,我们使用 getBoundingClientRect 方法获取被测量元素的宽度和高度,并将结果打印到控制台。这个操作在浏览器布局完成后同步执行,确保我们获取到的尺寸是最新的。

需要注意的是,由于 useLayoutEffect 在浏览器布局之后同步执行,因此它的执行会阻塞浏览器的渲染过程。因此,只有在需要同步更新 UI 或测量 DOM 元素时才使用 useLayoutEffect,避免造成性能问题。

本文使用 mdnice 排版

原文链接:https://juejin.cn/post/7257078736926081085 作者:demo123567

(0)
上一篇 2023年7月19日 上午10:01
下一篇 2023年7月20日 上午10:00

相关推荐

发表回复

登录后才能评论