React 18 组件的状态state

文章介绍了在React中如何使用useStateHook来管理组件的状态,当组件需要在多次渲染之间保持数据时,可以使用useState来声明state变量。useState返回一对值,一个是当前state,另一个是更新state的函数。文章还强调了state的私有性和不可见性,以及如何通过状态提升来同步多个组件的状态。
摘要由CSDN通过智能技术生成

参考文章

State:组件的状态

组件通常需要根据交互更改屏幕上显示的内容。输入表单应该更新输入字段,单击轮播图上的“下一个”应该更改显示的图片,单击“购买”应该将商品放入购物车。组件需要“记住”某些东西:当前输入值、当前图片、购物车。在 React 中,这种组件特有的记忆被称为 state

当普通的变量无法满足时

以下是一个渲染雕塑图片的组件。点击 “Next” 按钮应该显示下一个雕塑并将 index 更改为 1,再次点击又更改为 2,以此类推。但这个组件现在不起作用

import { sculptureList } from './data.js';

export default function Gallery() {
  let index = 0;

  function handleClick() {
    index = index + 1;
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img src={sculpture.url} alt={sculpture.alt}/>
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

handleClick() 事件处理函数正在更新局部变量 index。但存在两个原因使得变化不可见:

  1. 局部变量无法在多次渲染中持久保存。 当 React 再次渲染这个组件时,它会从头开始渲染——不会考虑之前对局部变量的任何更改。
  2. 更改局部变量不会触发渲染。 React 没有意识到它需要使用新数据再次渲染组件。

要使用新数据更新组件,需要做两件事:

  1. 保留 渲染之间的数据。
  2. 触发 React 使用新数据渲染组件(重新渲染)。

useState Hook 提供了这两个功能:

  1. State 变量 用于保存渲染间的数据。
  2. State setter 函数 更新变量并触发 React 再次渲染组件。

添加一个 state 变量

要添加 state 变量,先从文件顶部的 React 中导入 useState

import { useState } from 'react';

然后,替换这一行:

let index = 0;

将其修改为

const [index, setIndex] = useState(0);

index 是一个 state 变量,setIndex 是对应的 setter 函数。

这里的 [] 语法称为数组解构,它允许从数组中读取值。 useState 返回的数组总是正好有两项。

以下展示了它们在 handleClick() 中是如何共同起作用的:

function handleClick() {
  setIndex(index + 1);
}

现在点击 “Next” 按钮切换当前雕塑:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);

  function handleClick() {
    setIndex(index + 1);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img src={sculpture.url} alt={sculpture.alt}/>
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

Hook

在 React 中,useState 以及任何其他以“use”开头的函数都被称为 Hook

Hook 是特殊的函数,只在 React 渲染时有效。它们能让你 “hook” 到不同的 React 特性中去。

State 只是这些特性中的一个,之后还会遇到其他 Hook。

注意:Hooks ——以 use 开头的函数——只能在组件或自定义 Hook 的最顶层调用。 不能在条件语句、循环语句或其他嵌套函数内调用 Hook。Hook 是函数,但将它们视为关于组件需求的无条件声明会很有帮助。在组件顶部 “use” React 特性,类似于在文件顶部“导入”模块。

剖析 useState

当调用 useState 时,是在告诉 React 想让这个组件记住一些东西:

const [index, setIndex] = useState(0);

在这个例子里,希望 React 记住 index

注意:惯例是将这对返回值命名为 const [thing, setThing]。也可以将其命名为任何喜欢的名称,但遵照约定俗成能使跨项目合作更易理解。

useState 的唯一参数是 state 变量的初始值。在这个例子中,index 的初始值被useState(0)设置为 0

每次组件渲染时,useState 都会给一个包含两个值的数组:

  1. state 变量 (index) 会保存上次渲染的值。
  2. state setter 函数 (setIndex) 可以更新 state 变量并触发 React 重新渲染组件。

以下是实际发生的情况:

const [index, setIndex] = useState(0);
  1. 组件进行第一次渲染。 因为将 0 作为 index 的初始值传递给 useState,它将返回 [0, setIndex]。 React 记住 0 是最新的 state 值。
  2. 更新了 state。当用户点击按钮时,它会调用 setIndex(index + 1)index0,所以它是 setIndex(1)。这告诉 React 现在记住 index1 并触发下一次渲染。
  3. 组件进行第二次渲染。React 仍然看到 useState(0),但是因为 React 记住 了将 index 设置为了 1,它将返回 [1, setIndex]
  4. 以此类推!

赋予一个组件多个 state 变量

可以在一个组件中拥有任意多种类型的 state 变量。该组件有两个 state 变量,一个数字 index 和一个布尔值 showMore,点击 “Show Details” 会改变 showMore 的值:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);

  function handleNextClick() {
    setIndex(index + 1);
  }

  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleNextClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore ? 'Hide' : 'Show'} details
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img src={sculpture.url} alt={sculpture.alt}/>
    </>
  );
}

如果它们不相关,那么存在多个 state 变量是一个好主意,例如本例中的 indexshowMore。但是,如果发现经常同时更改两个 state 变量,那么最好将它们合并为一个。例如,如果有一个包含多个字段的表单,那么有一个值为对象的 state 变量比每个字段对应一个 state 变量更方便。 选择 state 结构在这方面有更多提示。

State 是隔离且私有的

State 是屏幕上组件实例内部的状态。换句话说,如果渲染同一个组件两次,每个副本都会有完全隔离的 state!改变其中一个不会影响另一个。

在这个例子中,之前的 Gallery 组件以同样的逻辑被渲染了两次。试着点击每个画廊内的按钮。会注意到它们的 state 是相互独立的:

import Gallery from './Gallery.js';

export default function Page() {
  return (
    <div className="Page">
      <Gallery />
      <Gallery />
    </div>
  );
}

这就是 state 与声明在模块顶部的普通变量不同的原因。 State 不依赖于特定的函数调用或在代码中的位置,它的作用域“只限于”屏幕上的某块特定区域。渲染了两个 <Gallery /> 组件,所以它们的 state 是分别存储的。

还要注意 Page 组件“不知道”关于 Gallery state 的任何信息,甚至不知道它是否有任何 state。与 props 不同,state 完全私有于声明它的组件。父组件无法更改它。这使你可以向任何组件添加或删除 state,而不会影响其他组件。

如果希望两个画廊保持其 states 同步怎么办?在 React 中执行此操作的正确方法是从子组件中删除 state 并将其添加到离它们最近的共享父组件中。也叫做状态提升

摘要

  • 当一个组件需要在多次渲染间“记住”某些信息时使用 state 变量。
  • State 变量是通过调用 useState Hook 来声明的。
  • Hook 是以 use 开头的特殊函数。它们能让你 “hook” 到像 state 这样的 React 特性中。
  • Hook 可能会让你想起 import:它们需要在非条件语句中调用。调用 Hook 时,包括 useState,仅在组件或另一个 Hook 的顶层被调用才有效。
  • useState Hook 返回一对值:当前 state 和更新它的函数。
  • 可以拥有多个 state 变量。在内部,React 按顺序匹配它们。
  • State 是组件私有的。如果在两个地方渲染它,则每个副本都有独属于自己的 state。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值