React 18 在组件间共享状态

这篇具有很好参考价值的文章主要介绍了React 18 在组件间共享状态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考文章

在组件间共享状态

有时候,希望两个组件的状态始终同步更改。要实现这一点,可以将相关 state 从这两个组件上移除,并把 state 放到它们的公共父级,再通过 props 将 state 传递给这两个组件。这被称为“状态提升”,这是编写 React 代码时常做的事。

状态提升

在这个例子中,父组件 Accordion 渲染了 2 个独立的 Panel 组件。

  • Accordion
    • Panel
    • Panel

每个 Panel 组件都有一个布尔值 isActive,用于控制其内容是否可见。

请点击 2 个面板中的显示按钮:

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)}>
          显示
        </button>
      )}
    </section>
  );
}

export default function Accordion() {
  return (
    <>
      <h2>哈萨克斯坦,阿拉木图</h2>
      <Panel title="关于">
        阿拉木图人口约200万,是哈萨克斯坦最大的城市。它在 1929 年到 1997 年间都是首都。
      </Panel>
      <Panel title="词源">
        这个名字来自于 <span lang="kk-KZ">алма</span>,哈萨克语中“苹果”的意思,经常被翻译成“苹果之乡”。事实上,阿拉木图的周边地区被认为是苹果的发源地,<i lang="la">Malus sieversii</i> 被认为是现今苹果的祖先。
      </Panel>
    </>
  );
}

我们发现点击其中一个面板中的按钮并不会影响另外一个,他们是独立的。

React 18 在组件间共享状态,前端,react,状态提升,在组件间共享状态,受控组件和非受控组件

假设现在想改变这种行为,以便在任何时候只展开一个面板。在这种设计下,展开第 2 个面板应会折叠第 1 个面板。该如何做到这一点呢?”

要协调好这两个面板,我们需要分 3 步将状态“提升”到他们的父组件中。

  1. 从子组件中 移除 state 。
  2. 从父组件 传递 硬编码数据。
  3. 为共同的父组件添加 state ,并将其与事件处理函数一起向下传递。

这样,Accordion 组件就可以控制 2 个 Panel 组件,保证同一时间只能展开一个。

第 1 步: 从子组件中移除状态

将把 Panel 组件对 isActive 的控制权交给他们的父组件。这意味着,父组件会将 isActive 作为 prop 传给子组件 Panel。先从 Panel 组件中 删除下面这一行

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

然后,把 isActive 加入 Panel 组件的 props 中:

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

现在 Panel 的父组件就可以通过 向下传递 prop 来 控制 isActive。但相反地,Panel 组件对 isActive 的值 没有控制权 —— 现在完全由父组件决定!

第 2 步: 从公共父组件传递硬编码数据

为了实现状态提升,必须定位到想协调的 两个 子组件最近的公共父组件:

  • Accordion(最近的公共父组件)
    • Panel
    • Panel

在这个例子中,公共父组件是 Accordion。因为它位于两个面板之上,可以控制它们的 props,所以它将成为当前激活面板的“控制之源”。通过 Accordion 组件将硬编码值 isActive(例如 true )传递给两个面板:

import { useState } from 'react';

export default function Accordion() {
  return (
    <>
      <h2>哈萨克斯坦,阿拉木图</h2>
      <Panel title="关于" isActive={true}>
        阿拉木图人口约200万,是哈萨克斯坦最大的城市。它在 1929 年到 1997 年间都是首都。
      </Panel>
      <Panel title="词源" isActive={true}>
        这个名字来自于 <span lang="kk-KZ">алма</span>,哈萨克语中“苹果”的意思,经常被翻译成“苹果之乡”。事实上,阿拉木图的周边地区被认为是苹果的发源地,<i lang="la">Malus sieversii</i> 被认为是现今苹果的祖先。
      </Panel>
    </>
  );
}

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

可以尝试修改 Accordion 组件中 isActive 的值,并在屏幕上查看结果。

第 3 步: 为公共父组件添加状态

状态提升通常会改变原状态的数据存储类型。

在这个例子中,一次只能激活一个面板。这意味着 Accordion 这个父组件需要记录 哪个 面板是被激活的面板。可以用数字作为当前被激活 Panel 的索引,而不是 boolean 值:

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

activeIndex0 时,激活第一个面板,为 1 时,激活第二个面板。

在任意一个 Panel 中点击“显示”按钮都需要更改 Accordion 中的激活索引值。 Panel 中无法直接设置状态 activeIndex 的值,因为该状态是在 Accordion 组件内部定义的。 Accordion 组件需要 显式允许 Panel 组件通过 将事件处理程序作为 prop 向下传递 来更改其状态:

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

现在 Panel 组件中的 <button> 将使用 onShow 这个属性作为其点击事件的处理程序:

import { useState } from 'react';

export default function Accordion() {
  const [activeIndex, setActiveIndex] = useState(0);
  return (
    <>
      <h2>哈萨克斯坦,阿拉木图</h2>
      <Panel
        title="关于"
        isActive={activeIndex === 0}
        onShow={() => setActiveIndex(0)}
      >
        阿拉木图人口约200万,是哈萨克斯坦最大的城市。它在 1929 年到 1997 年间都是首都。
      </Panel>
      <Panel
        title="词源"
        isActive={activeIndex === 1}
        onShow={() => setActiveIndex(1)}
      >
        这个名字来自于 <span lang="kk-KZ">алма</span>,哈萨克语中“苹果”的意思,经常被翻译成“苹果之乡”。事实上,阿拉木图的周边地区被认为是苹果的发源地,<i lang="la">Malus sieversii</i> 被认为是现今苹果的祖先。
      </Panel>
    </>
  );
}

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

这样,就完成了对状态的提升!将状态移至公共父组件中可以让你更好的管理这两个面板。使用激活索引值代替之前的 是否显示 标识确保了一次只能激活一个面板。而通过向下传递事件处理函数可以让子组件修改父组件的状态。

React 18 在组件间共享状态,前端,react,状态提升,在组件间共享状态,受控组件和非受控组件

受控组件和非受控组件

通常我们把包含“不受控制”状态的组件称为“非受控组件”。例如,最开始带有 isActive 状态变量的 Panel 组件就是不受控制的,因为其父组件无法控制面板的激活状态。

相反,当组件中的重要信息是由 props 而不是其自身状态驱动时,就可以认为该组件是“受控组件”。这就允许父组件完全指定其行为。最后带有 isActive 属性的 Panel 组件是由 Accordion 组件控制的。

非受控组件通常很简单,因为它们不需要太多配置。但是当你想把它们组合在一起使用时,就不那么灵活了。受控组件具有最大的灵活性,但它们需要父组件使用 props 对其进行配置。

在实践中,“受控”和“非受控”并不是严格的技术术语——通常每个组件都同时拥有内部状态和 props。然而,这对于组件该如何设计和提供什么样功能的讨论是有帮助的。

当编写一个组件时,应该考虑哪些信息应该受控制(通过 props),哪些信息不应该受控制(通过 state)。当然,可以随时改变主意并重构代码。

每个状态都对应唯一的数据源

React 应用中,很多组件都有自己的状态。一些状态可能“活跃”在叶子组件(树形结构最底层的组件)附近,例如输入框。另一些状态可能在应用程序顶部“活动”。例如,客户端路由库也是通过将当前路由存储在 React 状态中,利用 props 将状态层层传递下去来实现的!

对于每个独特的状态,都应该存在且只存在于一个指定的组件中作为 state。这一原则也被称为拥有 “可信单一数据源”。它并不意味着所有状态都存在一个地方——对每个状态来说,都需要一个特定的组件来保存这些状态信息。应该 将状态提升 到公共父级,或 将状态传递 到需要它的子级中,而不是在组件之间复制共享的状态。

你的应用会随着你的操作而变化。当你将状态上下移动时,你依然会想要确定每个状态在哪里“活跃”。这都是过程的一部分!文章来源地址https://www.toymoban.com/news/detail-691127.html

摘要

  • 当想要整合两个组件时,将它们的 state 移动到共同的父组件中。
  • 然后在父组件中通过 props 把信息传递下去。
  • 最后,向下传递事件处理程序,以便子组件可以改变父组件的 state 。
  • 考虑该将组件视为“受控”(由 prop 驱动)或是“不受控”(由 state 驱动)是十分有益的。

到了这里,关于React 18 在组件间共享状态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React 中的受控组件

    React 中的受控组件是由 React 组件管理其值的表单组件。它们的值受到 React 组件状态的控制,更新时会通过回调函数进行数据的处理。 受控组件的特点包括: 值由状态控制:受控组件的值是通过 React 组件的状态进行控制和更新的。 通过事件处理器更新值:受控组件通常配合

    2024年02月15日
    浏览(197)
  • React从入门到实战-事件处理,受控组件与非受控组件

    事件处理 通过onXxx属性指定事件处理函数(注意大小写) React使用的是自定义(合成)事件,而不是使用的原生DOM事件——为了更好的兼容性 React中的事件是通过事件委托方式处理的(委托给组件最外层的元素——为了更高效 通过event.target得到发生事件的DOM元素对象 收集表

    2024年02月12日
    浏览(173)
  • 初识React/JSX/组件/state/受控组件

                                               

    2024年02月12日
    浏览(60)
  • 在react中说说对受控组件和非受控组件的理解?以及应用场景

    简单来讲,就是受我们控制的组件,组件的状态全程响应外部数据 举例: 这时候当我们在输入框输入内容时,会发现输入的内容无法显示出来,此时input标签是一个可读的状态,因为value被this.state.username所控制,当用户输入时,this.state.username不会自动更新,这样的话input的内

    2024年01月22日
    浏览(195)
  • 深入探讨React受控组件的表单处理

    React中的受控组件是一种通过React状态管理表单元素值的方式。在这篇博客中,我们将深入探讨受控组件的使用,通过一个登录表单实例,了解其优势、实现方式以及在实际项目中的应用。 在React中,受控组件是由React状态管理表单元素值的一种形式。通过React的状态(state)来

    2024年01月25日
    浏览(54)
  • React 18 state 状态更新函数

    参考文章 设置组件 state 会把一次重新渲染加入队列。但有时可能会希望在下次渲染加入队列之前对 state 的值执行多次操作。为此,了解 React 如何批量更新 state 会很有帮助。 在下面的示例中,可能会认为点击 “+3” 按钮会使计数器递增三次,因为它调用了 setNumber(number +

    2024年02月13日
    浏览(40)
  • React 18 迁移状态逻辑至 Reducer 中

    参考文章 对于拥有许多状态更新逻辑的组件来说,过于分散的事件处理程序可能会令人不知所措。对于这种情况,可以 将组件的所有状态更新逻辑整合到一个外部函数中 ,这个函数叫作 reducer 。 随着组件复杂度的增加,将很难一眼看清所有的组件状态更新逻辑。例如,下面

    2024年02月10日
    浏览(61)
  • React 组件之状态

    没有什么是不可能的,只是需要找到正确的方法。 状态就是组件内部特有数据的载体(组件数据挂载方式),改变数据页面就会刷新,由组件自己设置和更改,也就是说由组件自己产生、维护,使用状态的目的就是为了在不同的状态下使组件的显示不同(自己管理),这在

    2024年02月05日
    浏览(37)
  • react组件状态

    一个前提:在react hook出来之前,函数式组件是没有自己的状态的,所以我们统一通过类组件来讲解 • 通过class的实例属性state来初始化 • state的值是一个对象结构,表示一个组件可以有多个数据状态 • 通过this.state来获取状态 classCounterextendsReact.Component{ • 语法 this.setState

    2024年02月10日
    浏览(35)
  • 【React】React18+Typescript+craco配置最小化批量引入Svg并应用的组件

    无论是哪种 Web UI 框架都不可避免的要与 Svg 打交道,那么批量引入才更方便管理 Svg 。 https://ryanhutzley.medium.com/dynamic-svg-imports-in-create-react-app-d6d411f6d6c6 https://github.com/airbnb/babel-plugin-inline-react-svg/issues/51 https://blog.shianqi.com/2017/12/13/Webpack/SVG-sprite/ https://pganalyze.com/blog/building-svg

    2024年04月10日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包