REACT 在组件之间共享状态

news2024/11/26 8:33:20

有时,您希望两个组件的状态始终一起变化。要做到这一点,请从他们俩身上删除状态,将其移动到他们最近的共同父级,然后通过道具将其传递给他们。这被称为提升状态,这是编写 React 代码时最常见的事情之一。

举例提升状态

在此示例中,父组件呈现两个单独的 s:AccordionPanel

  • Accordion
    • Panel
    • Panel

每个组件都有一个布尔状态,用于确定其内容是否可见。PanelisActive

按两个面板的显示按钮:

import { useState } from 'react';

function Panel({ title, children }) {
  const [isActive, setIsActive] = useState(false);
  return (
    <section className="panel">
      <h3>{title}</h3>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button onClick={() => setIsActive(true)}>
          Show
        </button>
      )}
    </section>
  );
}

export default function Accordion() {
  return (
    <>
      <h2>Almaty, Kazakhstan</h2>
      <Panel title="About">
        With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city.
      </Panel>
      <Panel title="Etymology">
        The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild <i lang="la">Malus sieversii</i> is considered a likely candidate for the ancestor of the modern domestic apple.
      </Panel>
    </>
  );
}

请注意,按下一个面板的按钮不会影响另一个面板,因为它们是独立的。

该图显示了一个由三个组件组成的树,一个父组件标记为 Accordion,两个子组件标记为 Panel。两个 Panel 组件都包含值为 false 的 isActive。

最初,每个 的状态都是 ,所以它们看起来都折叠了PanelisActivefalse

与上一个图相同的图,突出显示了第一个子 Panel 组件的 isActive,表示单击时 isActive 值设置为 true。第二个 Panel 组件仍包含值 false。

单击任一按钮只会单独更新该状态PanelPanelisActive

但现在假设您要更改它,以便在任何给定时间仅展开一个面板。在这种设计下,展开第二个面板应该会折叠第一个面板。你会怎么做?

要协调这两个面板,您需要通过三个步骤将其状态“提升”到父组件:

  1. 从子组件中删除状态。
  2. 从公共父级传递硬编码数据。
  3. 将状态添加到公共父级,并将其与事件处理程序一起传递。

这将允许组件协调两个 s,并且一次只能展开一个。AccordionPanel

步骤 1:从子组件中删除状态

您将把 的控制权交给其父组件。这意味着父组件将作为 prop 传递。首先从组件中删除以下行PanelisActiveisActivePanelPanel



const [isActive, setIsActive] = useState(false);

取而代之的是,添加到道具列表中:isActivePanel



function Panel({ title, children, isActive }) {

现在,父组件可以通过将其作为 prop 传递来控制。相反,组件现在无法控制 - 现在由父组件决定!PanelisActivePanelisActive

步骤 2:从公共父级传递硬编码数据

若要提升状态,必须找到要协调的两个子组件中最接近的公共父组件:

  • Accordion (最接近的共同父级)
    • Panel
    • Panel

在此示例中,它是组件。由于它位于两个面板的上方,并且可以控制它们的道具,因此它将成为面板当前处于活动状态的“真相来源”。使组件将硬编码值(例如,)传递给两个面板:AccordionAccordionisActivetrue

import { useState } from 'react';

export default function Accordion() {
  return (
    <>
      <h2>Almaty, Kazakhstan</h2>
      <Panel title="About" isActive={true}>
        With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city.
      </Panel>
      <Panel title="Etymology" isActive={true}>
        The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild <i lang="la">Malus sieversii</i> is considered a likely candidate for the ancestor of the modern domestic apple.
      </Panel>
    </>
  );
}

function Panel({ title, children, isActive }) {
  return (
    <section className="panel">
      <h3>{title}</h3>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button onClick={() => setIsActive(true)}>
          Show
        </button>
      )}
    </section>
  );
}

 

尝试编辑组件中的硬编码值,并在屏幕上查看结果。isActiveAccordion

步骤 3:将状态添加到公共父级

提升状态通常会改变存储为状态的内容的性质。

在这种情况下,一次只能有一个面板处于活动状态。这意味着公共父组件需要跟踪哪个面板是活动面板。它可以不使用值,而是使用数字作为状态变量的活动索引:AccordionbooleanPanel



const [activeIndex, setActiveIndex] = useState(0);

当 是 时,第一个面板处于活动状态,当它处于活动状态时,它是第二个面板。activeIndex01

单击其中的“显示”按钮需要更改 中的活动索引。A 不能直接设置状态,因为它是在 .组件需要显式允许组件通过将事件处理程序作为 prop 向下传递来更改其状态:PanelAccordionPanelactiveIndexAccordionAccordionPanel



<>
<Panel
isActive={activeIndex === 0}
onShow={() => setActiveIndex(0)}
>
...
</Panel>
<Panel
isActive={activeIndex === 1}
onShow={() => setActiveIndex(1)}
>
...
</Panel>
</>

内部现在将使用道具作为其 click 事件处理程序:<button>PanelonShow

import { useState } from 'react';

export default function Accordion() {
  const [activeIndex, setActiveIndex] = useState(0);
  return (
    <>
      <h2>Almaty, Kazakhstan</h2>
      <Panel
        title="About"
        isActive={activeIndex === 0}
        onShow={() => setActiveIndex(0)}
      >
        With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city.
      </Panel>
      <Panel
        title="Etymology"
        isActive={activeIndex === 1}
        onShow={() => setActiveIndex(1)}
      >
        The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild <i lang="la">Malus sieversii</i> is considered a likely candidate for the ancestor of the modern domestic apple.
      </Panel>
    </>
  );
}

function Panel({
  title,
  children,
  isActive,
  onShow
}) {
  return (
    <section className="panel">
      <h3>{title}</h3>
      {isActive ? (
        <p>{children}</p>
      ) : (
        <button onClick={onShow}>
          Show
        </button>
      )}
    </section>
  );
}

这样就完成了提升状态!将状态移动到公共父组件中允许您协调两个面板。使用活动索引而不是两个“显示”标志可确保在给定时间只有一个面板处于活动状态。将事件处理程序传递给子级允许子级更改父级的状态。

每个州的单一事实来源

在 React 应用程序中,许多组件将有自己的状态。某些状态可能像输入一样“存在于”叶子组件(树底部的组件)附近。其他状态可能“生活”在更靠近应用程序顶部的位置。例如,即使是客户端路由库,通常也是通过将当前路由存储在 React 状态,并通过 props 传递来实现的!

对于每个唯一的状态,您将选择“拥有”它的组件。这一原则也被称为具有“单一事实来源”。这并不意味着所有状态都存在于一个地方,而是对于每个状态,都有一个特定的组件来保存该信息。与其在组件之间复制共享状态,不如将其提升到其共同的共享父级,并将其传递给需要它的子级。

你的应用会随着你的使用而改变。通常,当您仍在弄清楚状态的每个部分“居住”的位置时,您会向下或向上移动状态。这都是过程的一部分!

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

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

相关文章

2024年3月 青少年等级考试机器人理论真题三级

202403 青少年等级考试机器人理论真题三级 第 1 题 流程图图例如下&#xff0c;与该图例功能对应的选项是&#xff1f;&#xff08; &#xff09; A&#xff1a;开始/结束 B&#xff1a;输入/输出 C&#xff1a;判断 D&#xff1a;处理 第 2 题 Arduino UNO/Nano主控板&am…

机器人学导论实验1—CoppeliaSim 平台介绍及初步使用BJTU

1. 实验内容分析 对实验内容的理解及关键点&#xff1a; 理解这个实验的关键点在于理解如何使用CoppeliaSim和MATLAB来控制和操作机器人。需要熟悉这两个工具的基本操作&#xff0c;例如如何加载场景、如何修改机器人参数、如何使用MATLAB客户端程序来控制机器人等。此外&#…

开源分布式爬虫管理平台:性能强悍!!【送源码】

简介 基于 Golang 的分布式爬虫管理平台&#xff0c;支持 Python、NodeJS、Go、Java、PHP 等多种编程语言以及多种爬虫框架。 谁适合使用 Crawlab? 网路爬虫工程师&#xff1a; 通过集成爬虫程序到 Crawlab&#xff0c;网路爬虫工程师可以聚焦于爬虫的核心解析逻辑&#xff0…

C语言学习【C语言基本数据类型二】

C语言学习【C语言基本数据类型二】 _Bool类型 C99标准添加了_Bool类型&#xff0c;用于表示布尔值&#xff0c;即逻辑值true和false&#xff0c;原则上仅占用1位存储空间&#xff1b; float、double和long double 记数法示例 C标准规定&#xff0c;float类型必须至少能表示…

2024CCPC郑州站超详细题解(含题面)ABFHJLM(河南全国邀请赛)

文章目录 前言A Once In My LifeB 扫雷 1F 优秀字符串H 随机栈J 排列与合数L Toxel 与 PCPC IIM 有效算法 前言 这是大一博主第一次参加xcpc比赛&#xff0c;虽然只取得了铜牌&#xff0c;但是收获满满&#xff0c;在了解了和别人的差距后会更加激励自己去学习&#xff0c;下面…

Linux修炼之路之权限

目录 引言 一&#xff1a;Linux中用户的分类 二&#xff1a;在Linux中的权限 1.权限的两种属性 1.人的属性 2.事物属性 -主要以文件属性为主 3.文件权限值的两种表示方式方法 2.更改文件访问者(拥有者&#xff0c;所属组&#xff0c;其他人)权限属性 3.更改文件的拥有…

vue3专栏项目 -- 四、前后端结合(下)

一、async 和 await 1、使用async 和 await 改造异步请求 在接触后端API以后就遇到了越来越多的异步请求&#xff0c;现在我们就使用async 和 await 改造异步请求。 async function是把返回内容包裹成个Promise返回Promise await 它在async function里面才起作用&#xff0…

【全开源】JAVA上门家政服务系统源码微信小程序+微信公众号+APP+H5

功能介绍 用户端&#xff1a;精准分类、支持家政、维修、万能服务、一口价、报价、线上、各类家政服务、优惠专区、师傅入驻、商家入驻、我的需求、补费明细、我的投诉 师傅端&#xff1a;接单池、消息通知、接单管理、今日订单、师傅入驻、我的钱包、实名认证 商家端&#…

【排序算法】之希尔排序

一、算法介绍 希尔排序(Shell Sort)是插入排序的一种&#xff0c;它是针对直接插入排序算法的改进。希尔排序又称缩小增量排序&#xff0c;因 DL.Shell 于 1959 年提出而得名。它通过比较相距一定间隔的元素来进行&#xff0c;各趟比较所用的距离随着算法的进行而减小&#xf…

系统设计 —— 随用户扩展

单服务器设置&#xff1a; 在单服务器设置中&#xff0c;所有内容都运行在一台服务器上。这包括网页应用程序、数据库、缓存等。 1*HQXZgCc5Vh8KooJHwKfzjw.png 图1.1 请求流程 1.最终用户通过域名&#xff08;myurl.com&#xff09;访问网站。请求发送到 DNS&#xff0c;将域名…

字符串函数(一):strcpy(拷贝),strcat(追加),strcmp(比较),及strncpy,strncat,strncmp

字符串函数 一.strcpy&#xff08;字符串拷贝&#xff09;1.函数使用2.模拟实现 二.strcat&#xff08;字符串追加&#xff09;1.函数使用2.模拟实现 三.strcmp&#xff08;字符串比较&#xff09;1.函数使用2.模拟实现 四.strncpy1.函数使用2.模拟实现 五.strncat1.函数使用2.…

[Kubernetes] sealos 部署 K8s v1.25.0 集群

文章目录 1.sealos 介绍2.操作系统基础配置3.安装部署 K8s4.验证 K8s 集群5.部署测试资源 1.sealos 介绍 Sealos 是一个基于 Kubernetes 内核的云操作系统发行版。它采用云原生方式&#xff0c;摒弃传统的云计算架构&#xff0c;转向以 Kubernetes 为云内核的新架构。这使得企…

Python从0到POC编写--函数

数学函数&#xff1a; 1. len len() 函数返回对象&#xff08;字符、列表、元组等&#xff09;长度或项目个数&#xff0c; 例如&#xff1a; str "python" len(str)2. range range() 函数返回的是一个可迭代对象&#xff08;类型是对象&#xff09;&#xff0c;…

安卓短视频一键搬运软件_V1.5.2 高级版

短视频一键搬运app是一款非常实用的视频处理软件&#xff0c;拥有各种各样的视频处理功能&#xff0c;可以帮助用户进行视频的多项处理&#xff0c;首先用户可以在这里为视频去除水印&#xff0c;打开视频文件过后&#xff0c;再把视频里面的水印内容框选出来&#xff0c;这样就…

从“金事通”带给我意想不到的来说--“数据是架构的中心”

背景 上周一个保险的销售人员来找我完成一定的售后流程。其中有一项是请我下载一个叫 金事通的 APP。说实在的我根本没听过。她说这是政治任务。我想不是有你们保险公司的APP了嘛。为什么还要我安装。没办法先安装吧。 经历了注册、人脸识别的步骤后。可以登录了。注册短信发…

Rx(Reactive Extensions)的由来

既然我们已经介绍了响应式编程&#xff0c;现在是时候了解我们的明星了:响应式扩展&#xff0c;通常简称为Rx。微软开发了Reactive扩展库&#xff0c;使其易于处理事件流和数据流。在某种程度上&#xff0c;时变值本身就是一个事件流;每个值更改都是一种类型的事件它会更新依赖…

交通地理信息系统实习教程(二)

这篇文章服务于GIS背景用户以及有志于GIS的朋友 操作源数据位置&#xff1a;【免费】交通地理信息系统实习二源数据资源-CSDN文库 软件安装包位置&#xff1a;【免费】TransCad-交通地理信息系统软件资源-CSDN文库 一、最短路径分析 1.1软件启动说明 这里需要给出一个必要的…

快来参加【顶尖赛事】LIC·2024 语言与智能技术竞赛

语言与智能技术竞赛&#xff08;LIC&#xff09;是由中国中文信息学会&#xff08;CIPS&#xff09;和中国计算机学会&#xff08;CCF&#xff09;联合主办&#xff0c;百度公司、中国中文信息学会评测工作委员会和中国计算机学会自然语言处理专委会承办的中文NLP顶级赛事&…

qt移植到imx6ull运行(qt部署到imx6ull)

这个事情对于小白来说确实不是很友好&#xff0c;会经常出现错误&#xff0c;我弄了两天终于弄好了 我主要参考了https://blog.csdn.net/m0_61738650/article/details/131269561 https://blog.csdn.net/m0_61738650/article/details/131171914这两个教程 我现在来简述一下流程…

AI+新能源充电桩数据集

需要的同学私信联系&#xff0c;推荐关注上面图片右下角的订阅号平台 自取下载。 随着我国新能源汽车市场的蓬勃发展&#xff0c;充电桩的需求量日益增加&#xff0c;充电桩的智能化程度不仅影响充电站运营商的经营效益&#xff0c;也大大影响着用户的充电体验。AI技术可以涵盖…