React State

State是组件的内存

网页交互过程中,组件通常需要根据交互来更改屏幕上显示的内容。输入表单应该更新输入字段,单击图像轮播上的“下一步”应该更改显示的图像,单击“购买”应该将产品放入购物车。组件需要记住一些特定的值,当前所发生的交互变化,用于储存这种变化的叫做State

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

  function handleClick() {
    index = index + 1;
  }
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <p>{index}</p>
    </>
  );
}

这是一段JSX代码,按理来说在渲染过后会出现一个NextButton和一个数字,点击Button以后数字值会增加1,但是实际点击过后页面上的数字0并不会跳转到1.

handleClick()更新局部变量index. 但是有两件事导致页面没有发生变化:

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

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

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

useStateHook 提供了这两件事:

  1. 用于在渲染之间保留数据的状态变量。
  2. 一个状态设置函数,用于更新变量并触发 React 再次渲染组件。

 

useState() 

useState是一个 React Hook,它让组件“记住”一些信息(State)。它返回两个值:当前状态和可用于更新它的函数。

const [state, setState] = useState(initialState);

您可以通过三个步骤向组件添加状态:

State是组件的内存。状态变量允许您保存一些随时间变化的信息,并且只限定于于你的组件。上图中,count保存点击次数。你可以将任何 JavaScript 值保持在State - 例如,当前输入文本、选定的图库图像或购物车的内容。

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}

对于这一段代码,效果于第一段没有使用State的代码大致相同,但是,在这个组件所渲染的页面中,单击Button时count值会实时变化渲染,这是因为使用了state,React知道它需要重新将新的值渲染到当前的页面上

useState的作用

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

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

在这种情况下,您希望 React 记住index.

惯例是将这对命名为const [thing, setThing]. 您可以将其命名为您喜欢的任何名称,但约定使跨项目的事情更容易理解。

useState唯一的参数是你的状态变量的初始值。在此示例中,index的初始值设置0为

useState(0)。

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

  1. 状态变量(index) 与您存储的值。
  2. 状态设置函数setIndex()可以更新状态变量并触发 React 再次渲染组件。

当这段代码打入后会发生的情况: 

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

  1. 第一次渲染时。你对useState传参0,因此会将index的初始值设置为0,所以它会返回        [0, setIndex]。React 记住0是最新的状态值。
  2. 状态有所更新时。当用户单击按钮时,它会调用setIndex(index + 1).当前index是0,所以是setIndex(1)。此时React就知道,index值被更新为了1,并且重新渲染用于呈现新画面。
  3. 组件第二次渲染。React 仍然会读取到useState(0),但是因为 React也会记得你设置了index值为1,所以它会返回[1, setIndex]。

如果你有两个相同的组件调用,他们的State的值是独立的,一个组件的State值改变不会影响到另一个组件

声明State

您可以在一个组件中声明多个State变量。您必须在组件的顶层声明它们,在任何条件或循环语句之外。该组件声明状态变量称为name和age:

 这使得组件可以“记住”多个独立的事物State——例如,不同的表单字段。

import { useState } from 'react';

export default function Form() {
  const [name, setName] = useState('Taylor');
  const [age, setAge] = useState(28);

  return (
    <>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button onClick={() => setAge(age + 1)}>
        Happy birthday!
      </button>
      <p>Hello, {name}. You are {age}.</p>
    </>
  );
}

 

 在这个例子中,我们有两个State,分别是nameage,我们在表单中输入相你想输入的名字,onChange触发name的set函数setName将输入的值设定为name的值,然后value属性获取name赋给表单更新输入框内容,同时更新下方渲染的名字。按下button使得age值加1,使得下方的年龄数也得到更新。

什么时候不需要使用

更新状态中的对象和数组

你也可以保持对象和数组的状态。但是,您应该始终替换状态中的对象,而不是修改现有对象。更新对象更新数组描述了有助于避免错误的常见模式。

import { useState } from 'react';
export default function MovingDot() {
  const [position, setPosition] = useState({
    x: 0,
    y: 0
  });
  return (
    <div
      onPointerMove={e => {
        setPosition({
          x: e.clientX,
          y: e.clientY
        });
      }}
      style={{
        position: 'relative',
        width: '100vw',
        height: '100vh',
      }}>
      <div style={{
        position: 'absolute',
        backgroundColor: 'red',
        borderRadius: '50%',
        transform: `translate(${position.x}px, ${position.y}px)`,
        left: -10,
        top: -10,
        width: 20,
        height: 20,
      }} />
    </div>
  )
}

特别情况

将相同的值传递给 setState

如果将当前状态传递给setState,React将跳过重新渲染组件

setCount(count); // Won't trigger a re-render

这是性能优化。React 使用Object.is()算法来比较这些值。

将更新程序函数传递给setState

您可以将函数传递setState. 这样的函数,就像在这个例子中一样,被称为“更新器”。React 将在下一次渲染期间调用您的更新程序来计算最终状态。

 此文章来源于React新文档React 中文文档(Beta 版) | React 中文文档 | React 中文网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值