React Native 从类组件到函数组件

1. 发展趋势

React Native社区中的趋势是朝向使用函数组件(Functional Components)和Hooks的方向发展,而不是使用类组件(Class Components)。

React Native自推出Hooks API以来,函数组件和Hooks的使用变得更加普遍和推荐。Hooks提供了更简洁、可读性更高的代码,并且在状态管理、生命周期等方面提供了更强大的功能。使用Hooks可以更容易地共享逻辑和状态逻辑,而无需使用类组件的复杂结构。

以下是一些关于为什么React Native社区更倾向于使用函数组件和Hooks的理由:

可读性和简洁性: 函数组件通常比类组件更短,更易于阅读和理解。Hooks的引入使得在函数组件中管理状态和副作用变得更为直观。

逻辑复用: Hooks使得逻辑的复用更加容易。你可以使用自定义Hooks将组件之间的逻辑进行抽象和共享,而不需要使用高阶组件或渲染属性。

更直观的副作用处理: 使用useEffect等Hooks来处理副作用相对于类组件中的生命周期方法更为直观。

更容易集成现代JavaScript特性: 使用函数组件和Hooks可以更容易地与ES6+和TypeScript等现代JavaScript特性集成。

更好的性能优化: Hooks使得React能够更好地进行性能优化,并且React Native的未来版本也更加注重性能。

2. Hooks vs Class

Hooks 提供了在函数组件中执行副作用和访问状态的能力。下面是一些常见的 Hooks 及其在类组件中对应的生命周期方法:

  1. useState - setState:
  • 函数组件: 使用 useState 来声明和更新状态。
  • 类组件: 使用 this.setState 来更新状态。
  1. useEffect - componentDidMount, componentDidUpdate, componentWillUnmount:

    • 函数组件: 使用 useEffect 来执行副作用,可以模拟生命周期方法的行为。
    • 类组件:
      • componentDidMount: 在组件挂载后调用。
      • componentDidUpdate: 在组件更新后调用。
      • componentWillUnmount: 在组件卸载前调用。
useEffect(() => {// componentDidMount 和 componentDidUpdate 的逻辑return () => {// componentWillUnmount 的逻辑};
}, [dependencies]);
  1. useContext - contextType:
* 函数组件: 使用 `useContext` 来访问 React 上下文。
* 类组件: 使用 `contextType` 来访问 React 上下文。
  1. useReducer - setStatethis.setState:
  • 函数组件: 使用 useReducer 来管理复杂状态逻辑。
  • 类组件: 可以使用 setState 或 this.setState,但 useReducer 更适合处理复杂状态逻辑。
  1. useCallback - shouldComponentUpdate:
  • 函数组件: 使用 useCallback 来记忆回调函数,以防止每次重新渲染时重新创建它。
  • 类组件: 在 shouldComponentUpdate 中进行优化,防止不必要的渲染。
  1. useMemo - shouldComponentUpdate:
  • 函数组件: 使用 useMemo 来记忆计算昂贵的计算结果。
  • 类组件: 在 shouldComponentUpdate 中进行优化,防止不必要的渲染。

这些是一些常见的 Hooks,它们为函数组件提供了类似于类组件生命周期方法的功能。使用 Hooks 可以更清晰地组织和重用逻辑。需要注意的是,使用 Hooks 时,每个 Hook 都是相互独立的,而类组件中的生命周期方法可能会涵盖多个生命周期阶段。

2.1 useState

useState 是 React Hooks 中用于在函数组件中添加状态的关键之一。它允许你在函数组件中添加和管理状态,而不需要使用类组件。useState 返回一个数组,其中包含两个元素:当前状态的值和一个更新状态的函数。

下面是 useState 的基本用法:

import React, { useState } from 'react';function MyComponent() {// 使用 useState 定义一个状态变量,初始值为 'initialValue'const [state, setState] = useState('initialValue');return (<div><p>Current State: {state}</p>{/* 使用 setState 函数来更新状态 */}<button onClick={() => setState('newValue')}>Update State</button></div>);
}export default MyComponent;

在上面的例子中,useState 被调用并传入初始状态 'initialValue',返回的数组包含当前状态值 state 和更新状态的函数 setState。通过点击按钮,可以触发 setState 函数来更新状态。

useState 的基本用法包括:

  • 定义状态: 调用 useState 来声明一个状态变量,并传入初始值。
  • 获取当前状态值: 使用返回的数组的第一个元素(例如,state)来获取当前状态的值。
  • 更新状态: 使用返回的数组的第二个元素(例如,setState)来更新状态。setState 函数接受新的状态值作为参数。

请注意,useState 可以在组件中多次调用,以添加多个状态变量。每个状态变量都有自己独立的 setState 函数。

import React, { useState } from 'react';function MyComponent() {const [count, setCount] = useState(0);const [text, setText] = useState('');return (<div><p>Count: {count}</p><button onClick={() => setCount(count + 1)}>Increment Count</button><p>Text: {text}</p><inputtype="text"value={text}onChange={(e) => setText(e.target.value)}/></div>);
}export default MyComponent;

在上面的例子中,MyComponent 组件有两个状态变量 counttext,每个都有自己的 setState 函数。

2.2 useEffect

useEffect 是 React Hooks 中用于处理副作用的关键之一。它在函数组件中提供了执行副作用的能力。useEffect 接受两个参数:

  • 一个函数,包含需要执行的副作用代码。
  • 一个可选的依赖数组,用于指定在依赖项发生变化时才重新运行 useEffect。
import React, { useEffect } from 'react';function MyComponent() {// 在组件挂载后执行一次useEffect(() => {// 执行副作用的代码// 清理函数(componentWillUnmount 的替代)return () => {// 在组件卸载前执行清理逻辑};}, [dependencies]); // 依赖项数组return (// 组件的 JSX);
}export default MyComponent;
  • Effect 函数: 第一个参数是一个函数,包含需要在每次渲染后执行的副作用代码。这个函数可以返回一个清理函数(cleanup function),用于在组件卸载时执行清理逻辑,类似于 componentWillUnmount。
  • 依赖项数组: 第二个参数是一个数组,包含影响副作用执行的变量。如果依赖项数组中的任何一个变量发生变化,useEffect 就会重新运行。如果省略依赖项数组,副作用将在每次组件渲染时都运行。
    以下是一些 useEffect 的常见用法:
  1. 只在组件挂载时执行副作用
useEffect(() => {// 执行副作用的代码return () => {// 在组件卸载前执行清理逻辑};
}, []);
  1. 在特定依赖项变化时执行副作用
useEffect(() => {// 执行副作用的代码return () => {// 在特定依赖项变化时执行清理逻辑};
}, [dependency1, dependency2]);
  1. 执行异步操作
useEffect(() => {const fetchData = async () => {try {// 异步操作,比如从 API 获取数据const result = await fetchDataFromApi();// 处理结果} catch (error) {// 处理错误}};fetchData();return () => {// 在组件卸载前执行清理逻辑};
}, [dependency]);

useEffect 的使用取决于具体的需求,可以根据需要执行副作用,并确保在组件卸载前进行必要的清理。

2.3 useContext

useContext 是 React Hooks 中用于访问 React 上下文的钩子。它允许你在函数组件中订阅 React 上下文的值,而无需使用 Context.Consumer

下面是 useContext 的基本用法:

  1. 创建上下文: 使用 React.createContext 创建一个上下文对象。
  2. 在顶层组件提供上下文的值: 使用 Context.Provider 在组件树的某个位置提供上下文的值。
  3. 在子组件中使用 useContext: 在需要访问上下文的子组件中使用 useContext 来获取上下文的值。

以下是一个简单的例子:

import React, { createContext, useContext } from 'react';// 创建一个上下文对象
const MyContext = createContext();// 在顶层组件提供上下文的值
function MyProvider({ children }) {const contextValue = 'Hello from Context';return (<MyContext.Provider value={contextValue}>{children}</MyContext.Provider>);
}// 在子组件中使用 useContext 获取上下文的值
function MyComponent() {const contextValue = useContext(MyContext);return <p>{contextValue}</p>;
}// 在应用的顶层组件中使用 MyProvider 包裹子组件
function App() {return (<MyProvider><MyComponent /></MyProvider>);
}export default App;

如果组件分别在不同的组件中, 则可以定义一个文件导出定义的 context:

import { createContext } from 'react';const MyContext = createContext();export default MyContext;

2.4 useReducer

useReducer 是 React Hooks 中用于管理复杂状态逻辑的钩子。它提供了一种可预测的方式来更新状态,尤其适用于处理具有多个可能操作的状态。使用 useReducer 时,你需要定义一个 reducer 函数,该函数负责处理不同的操作,并返回新的状态。

下面是 useReducer 的基本用法:

  1. 定义 reducer 函数: 创建一个接受当前状态和操作的函数,根据操作类型返回新的状态。reducer 函数的格式为 (state, action) => newState
  2. 使用 useReducer: 在组件中调用 useReducer 并传入 reducer 函数和初始状态。
  3. 得到当前状态和 dispatch 函数: useReducer 返回一个包含当前状态和 dispatch 函数的数组。
  4. dispatch 操作: 调用 dispatch 函数并传入一个操作对象,reducer 将根据操作类型来更新状态。
    以下是一个简单的例子:
import React, { useReducer } from 'react';// 定义 reducer 函数
const reducer = (state, action) => {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };case 'DECREMENT':return { count: state.count - 1 };default:return state;}
};// 使用 useReducer
function Counter() {const [state, dispatch] = useReducer(reducer, { count: 0 });return (<div><p>Count: {state.count}</p><button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button><button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button></div>);
}export default Counter;

在上面的例子中,reducer 函数接收当前状态和操作,根据操作类型更新状态。useReducer 返回一个包含当前状态和 dispatch 函数的数组。通过调用 dispatch 函数,并传入包含 type 属性的操作对象,可以触发 reducer 来更新状态。

useReducer 还支持传入一个可选的初始化函数,用于计算初始状态,例如:

const initialState = { count: 0 };const init = (initialState) => {return { count: initialState.count * 2 };
};const [state, dispatch] = useReducer(reducer, initialState, init);

在这个例子中,init 函数接收初始状态,并返回实际的初始状态。这可以是有用的,例如在初始状态需要基于某些计算的情况下。

使用 useReducer 的主要优势在于它使得状态逻辑更加模块化,特别是当有多个操作可能影响状态时。

2.5 useCallback

useCallback 是 React Hooks 中用于记忆回调函数的钩子。它的主要作用是在依赖不变的情况下,返回一个记忆化的回调函数,避免在每次渲染时创建新的回调函数。这有助于优化性能,特别是在子组件中使用时。

基本的使用方式如下:

import React, { useCallback } from 'react';function MyComponent({ onClick }) {// 使用 useCallback 包裹回调函数const memoizedCallback = useCallback(() => {// 回调函数的逻辑console.log('Callback executed!');},// 依赖项数组[/* dependencies */]);return (<button onClick={memoizedCallback}>Click me</button>);
}export default MyComponent;

在上面的例子中,useCallback 接收两个参数:一个回调函数和一个依赖项数组。它返回一个记忆化后的回调函数 memoizedCallback。如果依赖项数组中的值没有发生变化,memoizedCallback 将保持相同的引用,从而避免在每次渲染时重新创建回调函数。

常见的用法包括:

  1. 避免子组件的不必要渲染: 在将回调函数传递给子组件时,使用 useCallback 避免子组件不必要地重新渲染。
const memoizedCallback = useCallback(() => {// 回调函数的逻辑},[/* dependencies */]
);return <ChildComponent onClick={memoizedCallback} />;
  1. 作为依赖项传递给其他 Hook: 在使用其他 Hook 时,将 useCallback 的记忆化回调函数作为依赖项传递。
useEffect(() => {// 使用 memoizedCallback 作为依赖项someHook(memoizedCallback);
}, [memoizedCallback]);
  1. 避免在依赖项变化时触发 effect: 在使用 useEffect 时,通过使用 useCallback 避免在依赖项变化时触发 effect。
useEffect(() => {// 在 memoizedCallback 变化时执行 effect
}, [memoizedCallback]);

需要注意的是,过度使用 useCallback 可能会导致性能问题,因为每个记忆化的回调函数都需要额外的内存。因此,只在确实有性能问题或需要时使用 useCallback

2.6 useMemo

useMemo 是 React Hooks 中用于记忆化计算结果的钩子。它接受一个计算函数和依赖项数组,并返回计算结果的记忆化版本。这有助于避免在每次渲染时重新计算耗时的操作,提高性能。

基本的使用方式如下:

import React, { useMemo } from 'react';function MyComponent({ data }) {// 使用 useMemo 记忆化计算结果const memoizedResult = useMemo(() => {// 计算结果的逻辑console.log('Computing result...');return data.filter(item => item > 5);},// 依赖项数组[data]);return (<div><p>Result: {memoizedResult}</p></div>);
}export default MyComponent;

在上面的例子中,useMemo 接收两个参数:一个计算函数和一个依赖项数组。它返回一个记忆化后的计算结果 memoizedResult。如果依赖项数组中的值没有发生变化memoizedResult 将保持相同的引用,从而避免在每次渲染时重新计算结果。

常见的用法包括:

  1. 优化渲染性能: 避免在每次渲染时都执行昂贵的计算,只在依赖项变化时重新计算。
const memoizedResult = useMemo(() => {// 昂贵的计算逻辑},[/* dependencies */]
);
  1. 记忆化函数: 当需要在每次渲染时都返回一个新的函数,但只有在依赖项变化时才创建新函数时,可以使用 useMemo 记忆化函数。
const memoizedFunction = useMemo(() => {return () => {// 函数的逻辑};},[/* dependencies */]
);
  1. 避免重复计算: 当某个计算结果仅在特定依赖项变化时才发生变化时,使用 useMemo 避免重复计算。
const memoizedResult = useMemo(() => {// 仅在特定依赖项变化时才计算结果},[specificDependency]
);

需要注意的是,过度使用 useMemo 可能会导致性能问题,因为每个记忆化的结果都需要额外的内存。因此,只在确实有性能问题或需要时使用 useMemo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/586021.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE】多线程(7) -- 线程池的概念和简单实现

目录 1.线程池是什么 2.标准库中的线程池 2.1ThreadPoolExecutor 2.2构造方法参数介绍 2.3拒绝策略(面试易考) 2.4Executor的使用 3.实现线程池 1.线程池是什么 线程池是一种用来管理线程的机制&#xff0c;它可以有效地控制线程的创建、复用和销毁&#xff0c;从而提高程…

程序的编译、链接

目录 前言&#xff1a; 前置知识回顾 宏 宏定义常量 宏定义语句 宏定义函数 条件编译 应用场景 编译过程概览 预编译阶段 编译阶段 汇编阶段 链接阶段 前言&#xff1a; 在ANSI C的任何一种实现中&#xff0c;存在两种不同的环境&#xff0c;第1种是翻译环境&#x…

EE Vocabulary(电气工程词汇库)

前言 整理了一些EE&#xff08;电子工程&#xff09;和CS&#xff08;计算机&#xff09;专业的学生们阅读英文文献或写论文常用的一些词汇。 仓库GitHub地址&#xff1a;https://github.com/Phillweston/EE_Vocabulary 内容 仓库包含以下格式的电气工程词汇&#xff1a; …

GPT-5、开源、更强的ChatGPT!OpenAI公布2024年计划

年终岁尾&#xff0c;正值圣诞节热闹气氛的OpenAI写下了2024年的发展清单。 OpenAI联合创始人兼首席执行官Sam Altman在社交平台公布&#xff0c;AGI&#xff08;稍晚一些&#xff09;、GPT-5、更好的语音模型、更高的费率限制&#xff1b; 更好的GPTs&#xff1b;更好的推理…

代码随想录算法训练营第三十二天|122.买卖股票的最佳时机II、 55. 跳跃游戏、45.跳跃游戏II

122.买卖股票的最佳时机II 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;贪心算法也能解决股票问题&#xff01;LeetCode&#xff1a;122.买卖股票最佳时机II_哔哩哔哩_bi…

大数据- Hadoop入门

目录 &#x1f436;2.1 hadoop的简介 1. 概述 2. 什么是分布式&#xff1f; 3. Hadoop的指代 &#x1f436;2.2 hadoop的发展历程 &#x1f436;2.3 hadoop的版本介绍 &#x1f436;2.4 hadoop的常用端口号 &#x1f436;2.5 hadoop的设计目的 &#x1f436;2.6 hadoo…

Java集合/泛型篇----第二篇

系列文章目录 文章目录 系列文章目录前言一、说说List,Set,Map三者的区别二、Array与ArrayList有什么不一样?三、Map有什么特点四、集合类存放于 Java.util 包中, 主要有几 种接口前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。…

upload-labs Pass-03(黑名单验证,特殊后缀)问题纠正

php任何后缀名解析 背景&#xff1a;为了验证php解析不依靠后缀名&#xff0c;可以是任何后缀名&#xff0c;纠正upload-labs Pass-03&#xff08;黑名单验证&#xff0c;特殊后缀&#xff09;里所说的几个固定的后缀名理论是错误的。1 部署1.1 环境准备1.1.1 系统、内核&#…

【音视频 ffmpeg 学习】 跑示例程序 持续更新中

环境准备 在上一篇文章 把mux.c 拷贝到main.c 中 使用 attribute(unused) 消除警告 __attribute__(unused)/** Copyright (c) 2003 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated docu…

计算机毕业设计-----ssm流浪狗领养系统

项目介绍 我国的动物管理正处于起步阶段&#xff0c;注册在线的宠物数量非常有限&#xff0c;信息也很封闭&#xff0c;因此必须发挥民间力量扩容&#xff0c;加强宠物信息的宣传力度&#xff0c;使更多爱护动物的好心人可以领养宠物&#xff0c;同时也就收纳有家宠物信息&…

Efficient Classification of Very Large Images with Tiny Objects(CVPR2022补1)

文章目录 Two-stage Hierarchical Attention SamplingOne-stageTwo-Stage内存需求 Efficient Contrastive Learning with Attention Sampling Two-stage Hierarchical Attention Sampling 一阶段缩放是hw&#xff0c;提取的特征是h1w1&#xff0c; 二阶段缩放是uv&#xff08;…

Mongodb聚合操作中的$type

在mongodb查询语句中&#xff0c;用户可以通过指定$type值&#xff0c;查询出的符合字段类型的文档数据。在mongodb聚合操作中&#xff0c;也存在$type操作符。本文就聚合操作中的$type进行介绍。 定义 返回一个表示传入参数BSON类型的字符串。在聚合操作中&#xff0c;按照下…

leetcode贪心(最大子序列和、分发饼干、摆动序列)

455.分发饼干 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有…

iPortal内置Elasticsearch启动失败的几种情况——Linux

作者&#xff1a;yx 文章目录 前言一、端口占用二、ES启动过慢三、磁盘占用过高&#xff0c;导致ES变为只读模式 前言 在Linux环境启动iPortal后有时会出现搜索异常的情况&#xff0c;如下截图&#xff0c;这是因为Elasticsearch&#xff08;以下简称“ES”&#xff09;没启动…

快速理解ASCII、GBK、Unicode、UTF-8、ANSI

文章大部分内容来源于非官方说明&#xff0c;且无法用逻辑推理出结果&#xff0c;准确性仅供参考。 ASCII 计算机是老外发明的&#xff0c;想让计算机实现更多的功能&#xff0c;必然少不了把常用的字母和符号存进去&#xff0c;甚至包含一些特殊符号&#xff0c;于是ASCII码…

剑指 Offer(第2版)面试题 60:n 个骰子的点数

剑指 Offer&#xff08;第2版&#xff09;面试题 60&#xff1a;n 个骰子的点数 剑指 Offer&#xff08;第2版&#xff09;面试题 60&#xff1a;n 个骰子的点数解法 1&#xff1a;递归解法 2&#xff1a;动态规划 剑指 Offer&#xff08;第2版&#xff09;面试题 60&#xff1…

共享单车之数据可视化

文章目录 第1关&#xff1a;绘制地图第2关&#xff1a;绘制流量最高的五条线路的路程图 第1关&#xff1a;绘制地图 任务描述 本关任务&#xff1a;使用JSP在百度地图上绘制一条共享单车起始路程。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 如何创建地…

进阶学习——Linux系统服务器硬件认识与RAID磁盘

目录 一、服务器知识补充 1.硬件 2.服务器常见故障 二、认识RAID 1.什么是RAID 2.RAID的优点 3.RAID的实现方式 三、RAID磁盘陈列 1.RAID 0 磁盘陈列介绍——RAID 0 2.RAID 1 磁盘陈列介绍——RAID 1 3.RAID 5 磁盘陈列介绍——RAID 5 4.RAID 6 磁盘陈列介绍——RA…

vr体验馆用什么软件计时计费,如遇到停电软件程序如何恢复时间

vr体验馆用什么软件计时计费&#xff0c;如遇到停电软件程序如何恢复时间 一、软件程序问答 如下图&#xff0c;软件以 佳易王vr体验馆计时计费软件V17.9为例说明 1、软件如何计时间&#xff1f; 点击相应编号的开始计时按钮即可 2、遇到停电再打开软件时间可以恢复吗&…

【开源】基于Vue+SpringBoot的公司货物订单管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 客户管理模块2.2 商品维护模块2.3 供应商管理模块2.4 订单管理模块 三、系统展示四、核心代码4.1 查询供应商信息4.2 新增商品信息4.3 查询客户信息4.4 新增订单信息4.5 添加跟进子订单 五、免责说明 一、摘要 1.1 项目…