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 重新渲染,但不会触发计算函数的重新执行。

useCallBack

在 React 中,useCallback 是一个用于优化性能的 hooks 函数。它用于在函数组件中缓存函数引用,避免在每次渲染时都创建新的函数实例。这在处理传递给子组件的回调函数时特别有用,因为子组件可能会在每次渲染时都接收新的回调,导致子组件不必要的重新渲染。

useCallback 接收两个参数:回调函数和一个依赖数组。它将返回一个经过优化的回调函数,该函数只有在依赖数组中的依赖项发生变化时才会重新创建。如果依赖项不变,useCallback 将返回之前缓存的回调函数引用,从而避免不必要的函数创建。
以下是一些常见的使用场景:

  1. 传递给子组件的回调函数:当您将回调函数作为属性传递给子组件时,可以使用 useCallback 来缓存回调函数,以避免不必要的子组件重新渲染。这在大型应用中特别有用,其中有许多子组件需要接收回调函数作为属性。

  2. 避免额外的渲染:如果回调函数依赖于组件的某些状态或属性,但实际上并不需要在每次组件渲染时都创建新的函数实例,您可以使用 useCallback 并将相关依赖项添加到依赖数组中,以避免不必要的渲染。

  3. 使用在 useEffect 和 useMemo 中:当您将回调函数用作 useEffectuseMemo 的依赖项时,也可以使用 useCallback 来缓存回调函数,以确保依赖项在变化时能够得到更新。

  4. 优化性能:在大型应用中,如果有许多回调函数需要频繁创建,使用 useCallback 可以帮助优化性能,减少不必要的函数创建,提高应用的性能和响应性。

使用 useCallback 的基本语法如下:

import React, { useCallback } from 'react';

const MyComponent = ({ onButtonClick }) => {
  // 使用 useCallback 缓存回调函数
  const handleClick = useCallback(() => {
    // 执行点击处理逻辑
    // ...
    onButtonClick(); // 调用传递进来的回调函数
  }, [onButtonClick]); // 依赖数组中包含了传递进来的回调函数

  return (
    <div>
      <button onClick={handleClick}>Click Me</button>
    </div>
  );
};

在上面的示例中,使用 useCallback 来缓存 handleClick 回调函数。传递给 useCallback 的依赖数组 [onButtonClick] 表示只有当 onButtonClick 发生变化时,handleClick 才会重新创建。

如果不使用 useCallback,每次 MyComponent 组件重新渲染时,handleClick 都会被重新创建,即使 onButtonClick 没有发生变化。通过使用 useCallback,可以确保只有在 onButtonClick 发生变化时,handleClick 才会重新创建,从而避免子组件不必要的重新渲染。

useCallback 在性能优化方面是非常有用的,尤其是在大型应用中,当有大量的回调函数需要传递给子组件时。它可以帮助减少不必要的组件重新渲染,提高应用的性能和响应性。

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,避免造成性能问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值