首页 > 其他分享 >React高级Hook

React高级Hook

时间:2024-10-18 12:49:02浏览次数:8  
标签:const 函数 useMemo reducer 高级 React Hook state action

useReducer 

useReducer 是 React 提供的一个 Hook,用于在函数组件中使用 reducer 函数来管理组件的 state。它类似于 Redux 中的 reducer,但仅用于组件内部的状态管理。useReducer 可以使复杂的状态逻辑更加清晰和可维护。

基本用法

useReducer 接收一个 reducer 函数和一个初始状态,并返回当前的 state 和一个 dispatch 函数。你可以通过 dispatch 函数来触发 reducer 函数,并传递一个 action 对象,reducer 根据 action 来更新 state。

参数
  1. reducer (Function): 一个纯函数,它接收当前的 state 和一个 action 对象,并返回一个新的 state。
  2. initialState (any): 组件的初始状态。
  3. [init (Function)] (可选): 一个可选的初始化函数,如果提供,它将在 reducer 调用之前被调用,以生成初始 state。它接收 initialState 并返回经过初始化的 state。
返回值
  1. state (any): 当前的状态。
  2. dispatch (Function): 一个 dispatch 函数,它接收一个 action 对象,并调用 reducer 函数来更新 state。

示例

下面是一个简单的计数器组件示例,展示了如何使用 useReducer

seReducer 是 React 提供的一个 Hook,用于在函数组件中使用 reducer 函数来管理组件的 state。它类似于 Redux 中的 reducer,但仅用于组件内部的状态管理。useReducer 可以使复杂的状态逻辑更加清晰和可维护。

基本用法

useReducer 接收一个 reducer 函数和一个初始状态,并返回当前的 state 和一个 dispatch 函数。你可以通过 dispatch 函数来触发 reducer 函数,并传递一个 action 对象,reducer 根据 action 来更新 state。

参数
  1. reducer (Function): 一个纯函数,它接收当前的 state 和一个 action 对象,并返回一个新的 state。
  2. initialState (any): 组件的初始状态。
  3. [init (Function)] (可选): 一个可选的初始化函数,如果提供,它将在 reducer 调用之前被调用,以生成初始 state。它接收 initialState 并返回经过初始化的 state。
返回值
  1. state (any): 当前的状态。
  2. dispatch (Function): 一个 dispatch 函数,它接收一个 action 对象,并调用 reducer 函数来更新 state。

示例

下面是一个简单的计数器组件示例,展示了如何使用 useReducer

import React, { useReducer } from 'react';  
  
// 定义 action 类型  
const increment = () => ({ type: 'INCREMENT' });  
const decrement = () => ({ type: 'DECREMENT' });  
const reset = () => ({ type: 'RESET' });  
  
// 定义 reducer 函数  
const counterReducer = (state, action) => {  
  switch (action.type) {  
    case 'INCREMENT':  
      return { count: state.count + 1 };  
    case 'DECREMENT':  
      return { count: state.count - 1 };  
    case 'RESET':  
      return { count: 0 };  
    default:  
      throw new Error();  
  }  
};  
  
// 初始状态  
const initialState = { count: 0 };  
  
function Counter() {  
  const [state, dispatch] = useReducer(counterReducer, initialState);  
  
  return (  
    <div>  
      <h1>Count: {state.count}</h1>  
      <button onClick={() => dispatch(increment())}>Increment</button>  
      <button onClick={() => dispatch(decrement())}>Decrement</button>  
      <button onClick={() => dispatch(reset())}>Reset</button>  
    </div>  
  );  
}  
  
export default Counter;

详细说明

  1. 定义 action 类型:
    • incrementdecrementreset 是三个返回 action 对象的函数。每个 action 对象都有一个 type 属性,用于在 reducer 中识别 action。
  2. 定义 reducer 函数:
    • counterReducer 是一个纯函数,它接收当前的 state 和一个 action 对象,并返回一个新的 state
    • 根据 action.type,reducer 更新 state
  3. 初始状态:
    • initialState 是组件的初始状态,这里我们设置 count 为 0。
  4. 使用 useReducer:
    • 在 Counter 组件中,使用 useReducer Hook 传入 counterReducer 和 initialState
    • useReducer 返回当前的 state 和 dispatch 函数。
    • 通过 dispatch 函数调用不同的 action 来更新 state。

复杂示例

在实际应用中,useReducer 通常用于管理更复杂的状态。例如,假设我们有一个待办事项列表。

import React, { useReducer } from 'react';  
  
// 定义 action 类型  
const addTodo = (text) => ({ type: 'ADD_TODO', text });  
const toggleTodo = (id) => ({ type: 'TOGGLE_TODO', id });  
  
// 定义 reducer 函数  
const todoReducer = (state, action) => {  
  switch (action.type) {  
    case 'ADD_TODO':  
      return {  
        ...state,  
        todos: [...state.todos, { id: Date.now(), text: action.text, completed: false }],  
      };  
    case 'TOGGLE_TODO':  
      return {  
        ...state,  
        todos: state.todos.map((todo) =>  
          todo.id === action.id ? { ...todo, completed: !todo.completed } : todo  
        ),  
      };  
    default:  
      throw new Error();  
  }  
};  
  
// 初始状态  
const initialState = { todos: [] };  
  
function TodoApp() {  
  const [state, dispatch] = useReducer(todoReducer, initialState);  
  
  const handleAddTodo = (e) => {  
    const text = e.target.value.trim();  
    if (text) {  
      dispatch(addTodo(text));  
      e.target.value = '';  
    }  
  };  
  
  return (  
    <div>  
      <h1>Todo List</h1>  
      <input type="text" onKeyDown={(e) => e.key === 'Enter' ? handleAddTodo(e) : null} />  
      <button onClick={handleAddTodo}>Add Todo</button>  
      <ul>  
        {state.todos.map((todo) => (  
          <li key={todo.id} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>  
            <span onClick={() => dispatch(toggleTodo(todo.id))}>  
              {todo.text}  
            </span>  
          </li>  
        ))}  
      </ul>  
    </div>  
  );  
}  
  
export default TodoApp;

 useMemo

useMemo是React提供的一个自定义Hook,它允许你在渲染过程中执行一些昂贵的计算,并且仅在依赖项发生变化时重新计算。这有助于优化性能,避免在每次渲染时都重新计算相同的数值或对象。

基本语法
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • 第一个参数是一个返回需要记忆值的函数。
  • 第二个参数是一个依赖项数组,这个数组中的值会决定何时重新计算记忆值。
使用场景

useMemo适用于以下场景:

  • 当你有一个计算成本高昂的值,并且这个值在组件的某些渲染中可能保持不变时。
  • 当你想要避免在每次渲染时都重新执行昂贵的计算时。
注意事项
  • useMemo主要用于性能优化,不要滥用。
  • 只有当你确定计算是昂贵的且结果可以安全地在渲染之间共享时才应该使用。
  • useMemo不会阻止渲染,它只会优化计算过程。
使用案例

以下是一个使用useMemo的示例,假设我们有一个React组件,用于显示一个列表中所有项目的名称,并且这个列表可能非常大。我们可以使用useMemo来优化过滤操作,避免在每次渲染时都重新执行过滤逻辑。

import React, { useEffect, useState, useMemo } from 'react';  
  
const LargeListComponent = () => {  
  const [list, setList] = useState([]);  
  const [filterText, setFilterText] = useState('');  
  
  // 模拟一个大型列表的加载  
  useEffect(() => {  
    // 这里通常是从API获取数据,但为了简化,我们使用一个静态数组  
    const largeList = Array.from({ length: 10000 }, (_, i) => ({  
      id: i + 1,  
      name: `Item ${i + 1}`,  
    }));  
    setList(largeList);  
  }, []);  
  
  // 使用useMemo来优化过滤操作  
  const filteredList = useMemo(() => {  
    return list.filter(item =>  
      item.name.toLowerCase().includes(filterText.toLowerCase())  
    );  
  }, [list, filterText]);  
  
  return (  
    <div>  
      <input  
        type="text"  
        value={filterText}  
        onChange={(e) => setFilterText(e.target.value)}  
        placeholder="Filter items..."  
      />  
      <ul>  
        {filteredList.map(item => (  
          <li key={item.id}>{item.name}</li>  
        ))}  
      </ul>  
    </div>  
  );  
};  
  
export default LargeListComponent;

在这个例子中,useMemo接收一个过滤函数和一个依赖项数组[list, filterText]。每当listfilterText发生变化时,useMemo会重新执行过滤函数,并返回一个新的过滤后的列表。如果listfilterText都没有变化,那么useMemo会返回上一次计算的结果,从而避免不必要的过滤操作。

这个优化对于大型列表来说是非常有用的,因为它可以减少不必要的计算量,提高组件的渲染性能。

在React和Vue中,useMemo(React)和computed(Vue)都是用于计算派生状态(或称为“计算属性”)的工具,但它们在使用方式和底层实现上有所不同。

React中的useMemo

useMemo是React的一个Hook,它用于在函数组件中优化性能。当你有一个计算成本高昂的值,并且这个值在组件的某些渲染中可能保持不变时,useMemo可以帮助你避免不必要的计算。

useMemo接收一个创建函数和一个依赖项数组。当依赖项数组中的任何一个值发生变化时,创建函数会重新运行,并返回一个新的值。如果依赖项没有变化,那么useMemo会返回上一次计算的值,从而避免不必要的计算。

需要注意的是,useMemo主要用于性能优化,并且只有在你能确定计算是昂贵的且结果可以安全地在渲染之间共享时才应该使用。

Vue中的computed

在Vue中,computed属性用于声明式地计算派生状态。当你有一个基于组件响应式数据计算出来的值,并且你希望这个值在响应式数据变化时自动更新时,computed是非常有用的。

computed属性可以是基于一个或多个响应式依赖的函数,这些依赖可以是组件的data属性、props或其他computed属性。当这些依赖发生变化时,computed属性会自动重新计算,并且Vue会确保它的值是最新的。

useMemo不同,computed在Vue中是声明式的,并且它总是会在依赖变化时重新计算,而不是基于性能优化的考虑。此外,computed属性还可以被用作模板中的绑定,并且它们具有缓存行为,这意味着如果依赖没有变化,那么computed属性的值也不会变化。

总结

  • useMemo(React):一个性能优化工具,用于避免不必要的昂贵计算。它返回一个记忆化的值,这个值在依赖项没有变化时保持不变。
  • computed(Vue):一个声明式的计算属性,用于基于响应式依赖计算派生状态。它总是会在依赖变化时重新计算,并且具有缓存行为。

 

标签:const,函数,useMemo,reducer,高级,React,Hook,state,action
From: https://blog.csdn.net/m0_55049655/article/details/143050524

相关文章

  • 深入解析React DnD拖拽原理,轻松掌握拖放技巧!
    深入解析ReactDnD拖拽原理,轻松掌握拖放技巧! 我们是袋鼠云数栈UED团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。。本文作者:霁明一、背景1、业务背景业务中会有一些需要实现拖拽的场景,尤其是偏视觉方向以及......
  • TS高级类型-class
    创建一个class类classPerson{age:number//没有值但是有类型name="小明"//有默认值,类型推断是stringconstructor(age:number,name:string){//构造函数没有返回值,返回值不需要加类型this.age=agethis.name=name}//实例方......
  • vue3中的自定义hooks的使用,以及和mixin的区别
    1、理解hooks的概念:hook本质是一个函数,将setup函数中使用的CompositionAPI进行封装,类似于Vue2中的mixin2、mixin相比hook的缺点:(1)变量来源不明确(隐式传入),不利于阅读,使代码变得难以维护(2)同名属性、同名方法无法融合,可能会导致冲突3、例一:第一步:在src/hooks/index.js文件:imp......
  • 08_实现 reactive
    目录编写reactive的函数签名处理对象的其他行为拦截in操作符拦截for...in循环delete操作符处理边界新旧值发生变化时才触发依赖的情况处理从原型上继承属性的情况处理一个对象已经是代理对象的情况处理一个原始对象已经被代理过一次之后的情况浅响应与深响应代......
  • Next.js 与 React 全栈开发:整合 TypeScript、Redux 和 Ant Design
    在上一集,我们编写完毕导航页面,并且非常的美观,但是我们发现编写网站是存静态的,在现代的网站当中一般都是动静结合,也就是说部分数据是从数据库读取的,部分静态数据是写在网页上面的,因此这章讲述如何搭建一个数据库。搭建数据库(PostgreSQL)在这里我们使用容器的方法进行数据库搭建,这......
  • React 高级阶段学习计划
    React高级阶段学习计划目标深入理解React的渲染机制和性能优化。学会代码分割和懒加载。掌握单元测试和集成测试。学习TypeScript与React的结合。学习内容性能优化React.memoReact.memo:用于优化函数组件的性能,避免不必要的重新渲染。示例:importReact,{useState,u......
  • 2.6.ReactOS系统中从内核中发起系统调用
    2.6.ReactOS系统中从内核中发起系统调用2.6.ReactOS系统中从内核中发起系统调用文章目录2.6.ReactOS系统中从内核中发起系统调用前言前言上面我们已经可以看到用户空间(R3)进行系统调用的全过程即两种方法的具体实现。系统调用一般时从R3发起的。其实window也运行......
  • 高级java每日一道面试题-2024年10月17日-Web篇-常见的web攻击有哪些?
    如果有遗漏,评论区告诉我进行补充面试官:常见的web攻击有哪些?我回答:常见的Web攻击种类繁多,攻击者利用各种漏洞和技术手段来入侵网站、窃取数据或破坏服务。以下是一些最常见的Web攻击类型及其简要说明:1.SQL注入(SQLInjection,SQLi)描述:攻击者通过在输入字段......
  • Canvas 在前端中的高级应用
    一、引言在前端开发领域,HTML5的 <canvas> 元素为网页带来了强大的绘图和动画功能。它不仅可以用于绘制简单的图形,还能够实现复杂的交互效果和动画场景。以下将详细介绍 canvas 的使用方法,并展示一些高级案例。二、Canvas基础(一)创建Canvas元素在HTML页面中,可以通......
  • 深入探讨 Python 高级话题
    Python是一门灵活的高级编程语言,提供了许多独特的高级特性。这些特性不仅帮助开发者编写简洁、优雅的代码,还能提升代码的性能和可扩展性。在本篇博客中,我们将深入探讨一些高级话题,如元编程、动态类型、垃圾回收、内存管理、高性能计算等。11.1元编程与 type()元编程 是指......