React组件状态管理

news2024/12/24 9:33:56

React组件的状态管理是一个很重要的内容。从字面来理解,按钮是否可单击、图片是否显示等,这些都是状态。广义来讲,React组件的状态还1包括传入React的数据,例如某个组件要展示列表,列表的数据也是该组件的状态。总之,状态就是React UI中的数据。没有数据的项目是没有实际意义的,React的状态管理就是解决组件内部、组件之间的通信。React状态管理的重要性由此可见一斑。

5.3.1  state

在React class组件时代,状态就是this.state,使用this.setState进行更新。在Hooks中使用useState来获取和更新组件state。

React不会直接从代码中修改UI。例如,不会编写诸如“禁用按钮"“启用按钮"和“显示成功消息"等命令。相反,React将描述组件的不同视觉状态的UI(“初始状态"“输入状态"和“成功状态"),通过用户输入触发状态更改。

software-labs-client工程中的src/features/bar/components/Search.js组件是一个使用React构建的搜索按钮。Search.js的部分代码如下(注意它是如何使用状态变量来确定是启用还是禁用搜索按钮的):

01	import React, { useState, useEffect } from 'react';
02	import { useSelector } from 'react-redux';
03	import { FormattedMessage } from 'react-intl';
04	import _ from 'lodash';
05	import { selectPreferences } from '../../wrappers/selector';
06	import { Button } from 'antd';
07	
08	const Search = () => {
09	  const preferences = useSelector(selectPreferences);
10	  const countryCode = preferences.countryCode;
11	  const [disabled, setDisabled] = useState(false);
12	
13	  useEffect(() => {
14	    if(!countryCode){
15	      setDisabled(true);
16	      return;
17	    }
18	    setDisabled(false);
19	  }, [countryCode])
20	
21	  const handleSearch = async () => {
22	    if(disabled){
23	      return;
24	    }
25	    //发送ajax请求
26	    ......
27	  }
28	  
29	    return (
30	      <>
31	        <Button
32	          id="search-button"
33	          type="primary"
34	          onClick={handleSearch}
35	          disabled={disabled}
36	        >
37	          <FormattedMessage id="SEARCH"/></Button>
38	      </>
39	    );
40	  }
41	  
42	  export default Search;

代码解析:

l 第01行引入React、useState、useEffect。

l 第02行引入useSelector。

l 第03行引入FormattedMessage,用于对文案进行国际化处理。

l 第04行引入lodash工具库。

l 第05行引入selectPreferences函数,用于从Redux中查找preferences对象,该对象保存了用户当前的区域、国家和语言。

l 第06行从antd中引入Button组件。

l 第08~40行是Search组件的内容。

l 第09行从Redux中获取preferences。

l 第10行preferences中获取countryCode值。

l 第11行通过useState设置state状态,disabled的值为false,设置disabled值的函数是setDisabled。

l 第13~19行是useEffect的调用。如果countryCode为空,则设置disabled的值为true,即按钮不可单击。

5.3.2  props

有了状态与组件,自然就有了状态在组件间的传递,一般称为 “通信"。

父子通信通过props传递,比较简单。例如在software-labs-client项目中,打开src/features/ feedback/index.js文件,其中定义了FeedBack组件,代码如下:

01	import React, { useState } from 'react';
02	import _ from 'lodash';
03	import './index.scss';
04	import feedback_icon from '../../assets/images/feedback-icon.png'
05	import FeedBackModal from './components/FeedBackModal';
06	
07	const FeedBack = () => {
08	  const [visible, setVisible] = useState(false);
09	
10	  const handleCancel = () => {
11	    setVisible(false);
12	  }
13	
14	  const handleOk = () => {
15	    setVisible(false);
16	  }
17	
18	  const openModal = () => {
19	    setVisible(true);
20	  }
21	
22	  return (
23	    <div id="feedBackMod">
24	      <button type="button" className="btn btn-feedback" onClick={openModal}>
25	        <img src={feedback_icon} className="mr-2"/>
26	        <span>FEEDBACK</span>
27	      </button>
28	    <FeedBackModal visible={visible} handleCancel={handleCancel} handleOk={handleOk}/>
29	    </div>
30	  );
31	}
32	export default FeedBack;

代码解析:

           l 第24行,单击FEEDBACK按钮,执行click事件,调用openModal函数。

l 第28行父组件向子组件FeedBackModal/传递3个值,其中visible是布尔值,handleCancel和handleOk是函数。

FeedBack组件如图5.7所示,初始时只展示FEEDBACK按钮。

在FeedBackModal子组件中,通过props接收父组件FeedBack传递的值,FeedBackModal子组件的位置是src/features/feedback/ components/FeedBackModal.js,代码如下:

01	import React, { useState, useEffect } from 'react';
02	import _ from 'lodash';
03	import { Modal } from 'antd';
04	import './FeedBackModal.scss';
05	
06	const FeedBackModal = (props) => {
07	  const { visible, handleCancel, handleOk } = props;
08	 
09	  useEffect(() => {
10	    //......
11	  }, [visible])
12	
13	  const ModalHeader = () => {
14	    //......
15	  }
16	  const submit = async (v) => {
17	     //......
18	     handleOk();
19	  }
20	 const modalCancel = async () => {
21	     //......
22	     handleCancel()
23	  }
24	  return (
25	    <Modal
26	      title={ModalHeader()}
27	      open={visible}
28	      onCancel={modalCancel}
29	      wrapClassName="feedBackModal"
30	      footer={null}
31	    >
32	       //......
33	      <button type="submit" onClick={submit}>SEND FEEDBACK</button>
34	    </Modal>
35	  )
36	}
37	
38	export default FeedBackModal;

代码解析:

l 第03行引入antd的Modal组件。

l 第06~36行是子组件FeedBackModal的内容。其中第07行通过props获取父组件传递来的变量,分别是visible、handleCancel、handleOk;在第09~11行的useEffect函数中监测visible的变化并执行相关逻辑。

l 第33行,单击SEND FEEDBACK按钮后调用submit函数提交用户的反馈信息。第16~19行定义了submit函数,在这个函数中调用父组件传递的handleOk函数。

l 第28行,onCancel是antd的Modal组件自定义的属性,Modal是一个弹窗,单击弹窗中的取消按钮时调用modalCancel函数。第20~23行定义了modalCancel函数,在该函数中调用了父组件传递的handleCancel函数。

FeedBackModal组件如图5.8所示,单击FEEDBACK按钮时,visible为true,重新渲染组件后展示FeedBackModal;单击右上角的关闭按钮时,调用handleCancel函数关闭弹窗。

对于深层级、远距离组件之间的通信,可以采用“状态提升"+ props逐层传递的方式。也就是说将state从子组件中清除,并将其移动到最接近的公共父组件中,然后通过props逐层向下传递给子组件。这种方式被称为提升状态,是编写React代码时最常见的事情之一。

5.3.3  context

当组件之间共享的数据很多时,利用props逐层传递就显得既复杂又难以维护。于是React引入了context,一个用于解决组件“跨级"通信的官方方案。

context一般在顶层组件创建,方便数据的全局注入和全局共享。例如在顶层组件App.js中创建context,代码如下:

01	import React,{Component,createContext} from 'react';
02	import B from './B.js';
03	export const GlobalContext = createContext({name:'scw'});
04	class App extends Component { 
05	  constructor(props) { 
06	    super(props); 
07	  } 
08	  handleClick = (e) => { 
09	    console.log('组件B单击了'); 
10	  } 
11	  render() { 
12	    return ( 
13	      <GlobalContext.Provider value={{name:'scw1',onClick:this.handleClick.bind(this)}}>
14	        <B /> 
15	      </GlobalContext.Provider> 
16	    )
17	  } 
18	} 
19	export default App;

代码解析:

l 第1行引入createContext。

l 第2行引入B组件。

l 第3行用createContext创建context的初始默认值。参数可以是对象、字符串等任意类型的值。

l 第13行使用GlobalContext.Provider进行context全局注入,这里的value表示对context重新赋值。使用Provider在顶层组件注入context数据后,里层的所有子组件及其后代组件均可访问到对应的context数据。当Provider的value值发生变化时,它内部的所有消费组件都会重新渲染。

在B组件中消费context,代码如下:

01	import { GlobalContext } from './App'; 
02	class B extends Component { 
03	  render() { 
04	    return <GlobalContext.Consumer> 
05	      {
06	         (globalContext) => 
07	           <span onClick={globalContext.onClick}> {globalContext.name} </span> 
08	      } 
09	    </GlobalContext.Consumer> 
10	  } 
11	} 
12	export default B;

代码解析:

l 在第7行消费context的数据、onClick和name。

虽然context可以在全局注入变量使所有组件共享状态,但是并不建议大量使用context。因为尽管它可以减少逐层传递,但当组件结构复杂时,我们并不知道context是从哪里传过来的。context就像一个全局变量,而全局变量正是导致应用走向混乱的原因之一,给组件带来了外部依赖的副作用。因此,真正意义上的全局信息且信息不会更改,例如界面主题、用户信息等,才应该使用context。

本文节选自《React.js+Node.js+MongoDB企业级全栈开发实践》,获出版社和作者授权共享。

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

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

相关文章

Dynamic Coarse-to-Fine Learning for Oriented Tiny Object Detection(CVPR2023待补)

文章目录 BeginningAbstract挑战方法成果 Introduction引出问题早期的work及存在的问题近期的work及存在的问题our workContribution Related Work&#xff08;paper for me&#xff09;Oriented Object DetectionPrior for Oriented ObjectsLabel Assignment Tiny Object Dete…

【算法】算法题-20231221

这里写目录标题 一、830. 较大分组的位置二、657. 机器人能否返回原点三、771. 宝石与石头 一、830. 较大分组的位置 在一个由小写字母构成的字符串 s 中&#xff0c;包含由一些连续的相同字符所构成的分组。 例如&#xff0c;在字符串 s "abbxxxxzyy"中&#xff0…

【XML】TinyXML 详解

1、简介 优点&#xff1a; TinyXML 是一个简单、小型的 C XML 解析器&#xff0c;可以轻松集成到项目中。 TinyXML 解析 XML 文档&#xff0c;并根据该文档构建可读取、修改和保存的文档对象模型 (DOM) TinyXML 是在 ZLib 许可下发布的&#xff0c;因此可以在开源或商业代码中…

【SQL题目】连续日期的判断

【1.查询至少连续3天下单的用户】 思路1&#xff08;使用lead&#xff09;&#xff1a; distinct user_id,create_date去重&#xff0c;确保每个用户每天只有一条访问记录lead(create_date,2,‘9999-12-31’) over(partition by user_id order by create_date)根据用户分区&am…

模型实战(18)之C++ - tensorRT部署GAN模型实现人脸超分辨重建

模型实战(18)之C++ - tensorRT部署GAN模型实现人脸超分辨重建 一个实现人脸超分辨率重建的demo支持StyleGAN: GPEN or GFPGAN通过C++ - tensorrt 快速部署,推理速度每帧 在RTX3090上5.5ms+,RTX3050上10ms+下边是实现效果(图片来源于网络search,如若侵权,联系删除) 下边…

AI Native工程化:百度App AI互动技术实践

作者 | GodStart 导读 随着AI浪潮的兴起&#xff0c;越来越多的应用都在利用大模型重构业务形态&#xff0c;在设计和优化Prompt的过程中&#xff0c;我们发现整个Prompt测评和优化周期非常长&#xff0c;因此&#xff0c;我们提出了一种Prompt生成、评估与迭代的一体化解决方案…

YashanDB个人版体验总结

前言 YashanDB数据库具有多项功能特性。首先&#xff0c;它是一个分布式数据库&#xff0c;支持水平扩展&#xff0c;能够将数据分散到多个节点上&#xff0c;从而提高系统的可靠性和性能。其次&#xff0c;YashanDB数据库具备高可用性&#xff0c;支持主从复制和自动故障转移…

竞赛保研 基于Django与深度学习的股票预测系统

文章目录 0 前言1 课题背景2 实现效果3 Django框架4 数据整理5 模型准备和训练6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于Django与深度学习的股票预测系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff…

VS ASP.Net Core项目还原Packages包到本地(解决服务器没有网无法重新生成的问题)

问题背景 ASP.Net Core MVC项目&#xff0c;无法重新生成。 现场服务器没有网,放上去的代码无法通过nuget还原包到服务器&#xff0c;导致无法编译无法运行。 解决办法 将Packages还原到本机&#xff08;有网&#xff09;&#xff0c;然后再将代码放到服务器运行。 在有网的…

KoPA: Making Large Language Models Perform Better in Knowledge Graph Completion

本来这个论文用来组会讲的&#xff0c;但是冲突了&#xff0c;没怎么讲&#xff0c;记录一下供以后学习。 创新点 按照我的理解简单概述一下这篇论文的创新点 提出使用大模型补全知识图谱&#xff0c;并且融合知识图谱的结构信息提出一个新的模型KoPA模型&#xff0c;采用少…

Excel 获取当前行的行数

ROW() 获取当前行 ROW()1 获取当前行然后支持二次开发

java基础入门-23-【网络编程】

java基础入门-23-【网络编程】 32、网络编程1.什么是网络编程2.网络编程三要素1.1 IP1.2 总结1.3 IPV4的地址分类形式1.4 常见的CMD命令1.5 InetAddress类的使用1.6 端口和协议 2.UDP通信程序2.1 UDP发送数据2.2UDP接收数据2.3UDP通信程序练习2.4UDP三种通讯方式2.5UDP组播实现…

more的详细用法

概要&#xff1a; Linux中more的功能是分页显示文件内容 空格键显示下一屏(页)&#xff0c;回车键Enter显示下一行&#xff0c;q键退出 本篇所用系统是Ubuntu22.04 一、more filename more后面跟的是文件名&#xff0c;分页显示文件内容 二、more < filename more从…

在MacOS上Qt配置OpenCV并进行测试

一.Qt环境准备 上一篇博客我讲了如何下载配置OpenCV库&#xff0c;但是在Qt5.15.2使用OpenCV库时&#xff0c;出现了一个问题就是我下载的Qt5.15.2是x86架构的&#xff0c;不能对OpenCV库进行链接&#xff0c;而OpenCV库是arm架构的 直接使用Qt5.15.2编译链接OpenCV库链接头文件…

Leetcode—75.颜色分类【中等】

2023每日刷题&#xff08;六十五&#xff09; Leetcode—75.颜色分类 实现代码 class Solution { public:void sortColors(vector<int>& nums) {int red 0, white 0, blue 0;for(auto num: nums) {if(num 0) {red;} else if(num 1) {white;} else {blue;}}for…

1. 创建型模式 - 工厂方法模式

亦称&#xff1a; 虚拟构造函数、Virtual Constructor、Factory Method 意图 工厂方法模式是一种创建型设计模式&#xff0c; 其在父类中提供一个创建对象的方法&#xff0c; 允许子类决定实例化对象的类型。 问题 假设你正在开发一款物流管理应用。 最初版本只能处理卡车运输…

PnetLab[网络虚拟化实验平台]下载地址

Pnet是一款分组网络仿真工具实验室和EVE-NG类似&#xff0c;由于官方提供的下载地址对我大国内域网络并不友好&#xff0c;特地将资源搬运至此。 PNETLAB-5.1.2.ova 下载 访问码&#xff1a; h2or 5.3.11升级包 下载 访问码&#xff1a; quu9 PNET_4.2.10.ova 下载 访问码&…

【C语言】指针详解(二)

目录 1.指针变量类型的意义 1.1指针的解引用 1.2指针 - 整数 1.3void*指针 2.const修饰指针 2.1const修饰变量 2.2const修饰指针变量 1.指针变量类型的意义 1.1指针的解引用 指针变量的大小和类型无关&#xff0c;只要是指针变量&#xff0c;在同一个平台下&#xff0…

技术人的年终总结报告,请笑纳

背景 年底了&#xff0c;部门间&#xff0c;小组间不可避免的需要写年终总结报告。我相信很多朋友这件事肯定比较反感。认为这些东西都是表面形式&#xff0c;没有任何意义&#xff1b;亦或对于专心搞开发的人&#xff0c;对于这种报告并不擅长&#xff0c;不知道如何下手&…

openGuass:极简版安装

目录 一、openGauss简介 二、初始化安装环境 1.创建安装用户 2.修改文件句柄设置 ​3.修改SEM内核参数 4.关闭防火墙 6.禁用SELINUX 7.安装依赖软件 8.重启服务器 三、安装数据库 1.下载安装包 2.创建安装目录 3.解压安装包 4.执行安装 5.验证安装 四、gsql工具…