react 常用钩子 hooks 总结

文章目录

          • React钩子概念图
            • 状态管理钩子 state management
            • 副作用钩子 effect hooks
            • 引用钩子 Ref hooks
            • 上下文钩子
            • 其他钩子
            • 过渡钩子 处理过渡效果
            • 性能优化钩子 performance hooks
            • React 19 新钩子


React钩子概念图
状态管理钩子 state management

useState useReducer useSyncExternalStore

useState 最常用钩子

const [value, setValue] = useState('')
const handleChange = (e) => {
    setValue(e.target.value)
}

#捕获用户输入值的变化
import React, { useState } from 'react';

function ToggleComponent() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <>
      
      {isVisible && 
Content to Show/Hide
} ); } export default ToggleComponent; # 控制显隐

useReducer 管理更为复杂状态的钩子

在一个reducer函数内管理状态

import React, { useReducer } from 'react';

// Reducer 函数
const reducer = (state, action) => {
  switch (action) {
    case 'increment':
      return state + 1;
    default:
      return state; // 默认返回当前状态
  }
};

function Counter() {
  const [count, dispatch] = useReducer(reducer, 0);

  return (
    <>
      

Count: {count}

); } export default Counter;

这个其实有点类似 Vue 的 vuex 两者设计思想类似 学过这两种语言的应该会有感受

相似点

  1. 状态定义
    • useReducer 中,初始状态通过 useReducer(reducer, initialState) 定义。
    • 在 Vuex 中,初始状态通过 state 属性定义。
  2. 状态更新逻辑
    • useReducer 中,reducer 函数负责根据 action 计算新的状态。
    • 在 Vuex 中,mutations 是唯一可以修改状态的地方,类似于 reducer
  3. 触发状态更新
    • useReducer 中,通过 dispatch(action) 触发状态更新。
    • 在 Vuex 中,通过 commit('mutation')dispatch('action') 触发状态更新。
  4. 集中化管理
    • 两者都提供了一种集中化的方式管理状态,避免了组件内部直接操作状态的混乱。

代码对比

React useReducer

import React, { useReducer } from 'react';

const initialState = 0;

// Reducer 函数
const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return state + 1;
    case 'decrement':
      return state - 1;
    default:
      return state;
  }
};

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

  return (
    <>
      

Count: {count}

); } export default Counter;

Vuex Store

// Vuex store
const store = new Vuex.Store({
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    },
  },
  actions: {
    increment({ commit }) {
      commit('increment');
    },
    decrement({ commit }) {
      commit('decrement');
    },
  },
});

// Vue 组件
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>

<script>
export default {
  computed: {
    count() {
      return this.$store.state.count;
    },
  },
  methods: {
    increment() {
      this.$store.dispatch('increment');
    },
    decrement() {
      this.$store.dispatch('decrement');
    },
  },
};
</script>

主要区别

特性 React useReducer Vuex
作用范围 适用于单个组件或父子组件间的状态管理 适用于全局状态管理(跨多个组件)
触发方式 dispatch(action) commit('mutation')dispatch('action')
是否支持异步操作 不直接支持,需要结合其他工具(如 useEffect 支持异步操作(通过 actions
模块化 需要手动组织代码结构 提供模块化支持(modules
学习曲线 较低,适合小型到中型应用 较高,适合中大型应用
import React, { useReducer } from 'react';

// 初始状态
const initialState = { email: '', password: '' };//初始值由 initialState 定义:{ email: '', password: '' }。

// Reducer 函数
// 它接收一个 action 对象(通常包含 type 和可选的 payload),并将这个 action 传递给 reducer。
// reducer 根据 action.type 和 action.payload 计算并返回新的状态。
const reducer = (state, action) => {
  switch (action.type) {
    case 'SET_EMAIL':
      return {
        ...state,
        email: action.payload,
      };
    case 'SET_PASS':
      return {
        ...state,
        password: action.payload,
      };
    default:
      return state;
  }
};

function LoginForm() {
  const [state, dispatch] = useReducer(reducer, initialState); // state 是当前的状态对象,在这里它是一个包含 email 和 password 的对象。
    //每次调用 dispatch 时,state 会根据 reducer函数 的逻辑更新为新的值。

  return (
    
{/* 绑定 email 输入框 */} { dispatch({ type: 'SET_EMAIL', payload: e.target.value }); }} placeholder="Enter email" /> {/* 绑定 password 输入框 */} { dispatch({ type: 'SET_PASS', payload: e.target.value }); }} placeholder="Enter password" /> {/* 显示当前状态 */}

Email: {state.email}

Password: {state.password}

); } export default LoginForm;

useSyncExternalStore 很少用 将非react状态钩子存储到react中

副作用钩子 effect hooks

useEffect useLayoutEffect useInsertionEffect

const [count, setCount] = useState(0)

useEffect(() => {
	document.title = `You clicked ${count} times`
},[count])
//给 useEffect  提供一个运行函数  传入依赖项数组 依赖项数组变化时函数运行


副作用函数一般有两种 比如事件驱动副作用 点击按钮等事件 第二种 渲染驱动副作用 页面渲染后运行 调取接口

const ref = useRef(null)

useEffect(() => {
    if(isPlaying){
        ref.current.play()
    }else{
        ref.current.pause()
    }
},[isPlaying])

useLayoutEffect react 绘制后运行

useEffect 异步执行 钩子不会阻塞浏览器绘制(paint),这意味着它会在浏览器完成渲染后异步执行。这是最常用的副

作用钩子,适用于大多数情况,比如数据获取、订阅或者手动DOM更新等。

useLayoutEffect 会在所有的 DOM 变更之后同步执行。这可以保证在任何浏览器绘制之前,所有的 DOM 操作已经完成。因此,如果

你的副作用涉及到 DOM 操作,并且这些操作会影响到页面的布局或视觉效果,你应该使用 useLayoutEffect 来避免闪烁或其他视觉问

题。

const ref = useRef(null)
const [tooltipHeight, setTooltipHeight] = useState(0)

useLayoutEffect(() => {
    const {height} = ref.current.getBoundingClientRect()
    setTooltipHeight(height)
},[])

useInsertionEffect 在渲染过程中插入样式 它可以让你在组件渲染之前插入样式定义,从而避免样式闪烁或未定义样式的问题。很少使

引用钩子 Ref hooks

useRef useImperativeHandle

useRef 访问dom实例 ref.current

const [timer, setTimer] = useState(0);
const intervalRef = useRef();
//启动计时器函数
const startTimer = () => {
    intervalRef.current = setInterval(() => {
        setTimer((prevTimer) => prevTimer + 1);
    }, 1000);
};
//startTimer 函数通过 setInterval 每隔 1 秒调用一次回调函数,该回调函数将 timer 状态增加 1。
//intervalRef.current 存储了 setInterval 返回的定时器 ID,以便稍后可以停止计时器。
// 停止计时器
const stopTimer = () => {
    clearInterval(intervalRef.current);
};

Timer: {timer} seconds

useImperativeHandle 也是一种引用钩子 很少使用 当你需要在父组件中操作子组件的某些功能,但又不希望暴露整个子组件实例时。

父组件获取子组件输入框的焦点

父组件

import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
  const childRef = useRef();

  const handleFocus = () => {
    childRef.current.focusInput();
  };

  const handleClear = () => {
    childRef.current.clearInput();
  };

  return (
    
); } export default ParentComponent;

子组件

import React, { useRef, useImperativeHandle, forwardRef } from 'react';

const ChildComponent = forwardRef((props, ref) => {
  const inputRef = useRef();

  // 自定义暴露的方法
  useImperativeHandle(ref, () => ({
    focusInput: () => {
      inputRef.current.focus();
    },
    clearInput: () => {
      inputRef.current.value = '';
    },
  }));

  return ;
});

export default ChildComponent;

useImperativeHandle 定义了两个方法:

  • focusInput:让输入框获得焦点。

  • clearInput:清空输入框的内容。

  • 父组件只能调用这两个方法,而不能直接访问 inputRef 或其他内容。

  • useImperativeHandle 必须与 forwardRef 配合使用,因为只有 forwardRef 才能将 ref 传递到子组件。

上下文钩子

useContext

读取上下文值

//1 创建context
const AppContext = createContext()
//2 用Provider组件包裹

	      

//3 useContext 获取值
function Title(){
    const text = useContext(AppContext)
    return 

{text}

}
其他钩子

useDebugValue useId

useDebugValue devtool调试用 很少使用

useId 创建唯一id 但不能用作key

function Form() {
  return (
    
); } function EmailInput({ name }) { const id = useId(); return ( <> ); }
过渡钩子 处理过渡效果

useTransition

useDeferredValue

useTransition 指定状态更新 不紧急

const [filter, setFilter] = useState('');
const [inputValue, setInputValue] = useState('');
const [isPending, startTransition] = useTransition();

const filteredItems = items.filter(item => item.includes(filter));

 {
    setInputValue(event.target.value);
    startTransition(() => {
      setFilter(event.target.value);
    });
  }}
  placeholder="Type to filter..."
/>
{isPending ? 

Loading...

: filteredItems.map(item =>
{item}
)}

useDeferredValue 延迟状态更新

性能优化钩子 performance hooks

useMemo useCallback

useMemo 提升性能 useMemo必须返回一个值

  • useMemo 是一个 React Hook,用于缓存计算结果,避免在每次渲染时都重新计算。
function SumComponent({ numbers }) {
    const sum = useMemo(() => {
        return numbers.reduce((total, n) => total + n, 0);
    }, [numbers]);
    
    return 

Sum: {sum}

; } //接收一个数字数组 numbers 作为 props,并计算这些数字的总和。通过使用 useMemo,确保了只有在 numbers 发生变化时才重新计算总 //和,从而提高了组件的性能,避免了不必要的重复计算。
import React, { useMemo } from 'react';

function SumComponent({ numbers }) {
  // 使用 useMemo 缓存计算结果
  const sum = useMemo(() => {
    console.log('Calculating sum...');
    return numbers.reduce((total, num) => total + num, 0);
  }, [numbers]); // 只有当 numbers 发生变化时才重新计算

  return (
    

Sum: {sum}

); } export default function App() { const [numbers, setNumbers] = React.useState([1, 2, 3, 4, 5]); const [count, setCount] = React.useState(0); // 添加一个随机数到数组中 const addRandomNumber = () => { setNumbers([...numbers, Math.floor(Math.random() * 100)]); }; return (

Current Count: {count}

); }

useCallback 缓存回调函数

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

  const increment = useCallback(() => {
    setCount((c) => c + 1);
  }, []);

  return (
    <>
      
{count}
; }
React 19 新钩子

useFormStatus useFormState useOptimistic use

你可能感兴趣的:(react,react.js,javascript,前端)