React Native 状态管理 - useState

前言

在传统的移动端开发中,页面的展示和数据是分开管理的。比如在 iOS 中如果我们要显示一个标题的话,会使用下面这种命令式 UI 的方式去实现,如 UIKit 中的控件:

ini 复制代码
// 先设置 UILabel 的样式
let titleLabel = UILabel(frame: .zero)
titleLabel.textColor = .black
self.titleLabel = titleLabel

// 然后加载完数据之后,再去设置内容
self.titleLabel.text = mode.title

这样实现存在一个问题就是代码分离,实现完控件之后我们还需要等网络数据回来之后再去修改控件的展示。

使用了状态管理的声明式 UI 就解决了上面存在的问题。我们只负责实现完控件之后将其和状态管理的变量绑定,之后我们只需要操作状态管理的变量即可,控件的样式会自动去更新。在 React Native 中,useState 就是来进行状态管理的。

首先,我们来看下它是如何使用的。

useState 的使用

第一步,我们需要导入 React 来使用 useState:

javascript 复制代码
import { useState } from 'react';

接下来,在自定义的组件中去使用它:

javascript 复制代码
export default function Counter() {
  const [counter, setCounter] = useState(1);

  function counterIncreate() {
    setCounter(counter + 1);
  }

  return (
    <>
      <View style={{ width: '100%', height: '200rpx' }}>
        <Text style={{ width: '100rpx', height: '30rpx' }}>{`数量:${counter}`} </Text>
        <TouchableOpacity style={{ width: '100rpx', height: '60rpx' }} onPress={() => counterIncreate()}>
          <Text style={{ width: '50rpx', height: '30rpx' }}>增加</Text>
        </TouchableOpacity>
      </View>
    </>
  );
}

上面的代码绘制了两个组件,一个是显示当前数量的文本组件,一个是增加数量的按钮组件。然后声明了一个 counterIncreate() 函数用来更新 counter 的值。 最后将 counter 变量与显示数量的文本组件进行绑定。

核心代码就是下面的这两行:

scss 复制代码
// 组件与变量进行绑定
<Text style={{ width: '100rpx', height: '30rpx' }}>{`数量:${counter}`} </Text>
// 点击按钮的时候去修改状态变量
setCounter(counter + 1);

上面的代码运行之后,点击增加按钮,数量加1之后会自动进行渲染。

useState 函数

scss 复制代码
const [counter, setCounter] = useState(1);

通过上面的代码可以看到,useState() 接受一个任意类型的初始值,然后返回一个数组。数组包含一个状态变量,变量的初始值是函数传进去的初始值;一个状态变量对应的 set 函数。关于数组内的命名约定俗成的格式是下面这种格式:

  • xxx, setXxx\] xxx 为变量名。

scss 复制代码
// set 命名为 setCounter1
const [counter, setCounter1] = useState(1);

function counterIncreate() {
   setCounter1(counter + 1);
}

但建议还是按照约定俗成的格式去命名。

数据的不变性

对与状态变量,是有不可变性的。我们只能通过返回的 set 函数去修改它的值。我们需要使用 const 去修饰。我们不能通过直接修改状态变量的值去更新渲染组件。比如下面的代码:

scss 复制代码
const [counter, setCounter] = useState(1);
function counterIncreate() {
  // 报错,因为 counter 是不可变的。
  counter = counter + 1;
}

即使我们用 let 修饰,虽然不会报错,但也无法进行组件状态的更新:

ini 复制代码
let [counter, setCounter] = useState(1);

function counterIncreate() {
  counter = counter + 1;
}

原因是 React Native 是在返回的 setState 函数中去处理状态更新的相关逻辑,所以 counter = counter + 1 是无法触发组件的状态更新。

如何获取当前的状态值

如果我们的需求是在更新状态的同时还要记录下当前的状态值,那么需要像下面这种方式去获取:

ini 复制代码
  function counterIncreate() {
    // counter = 1
    setCounter(counter + 1);
    const result = counter + 1;
    console.log(result); // 2
  }

如果我们这样写是无法正确的获取当前状态值的:

ini 复制代码
  function counterIncreate() {
    // counter = 1
    setCounter(counter + 1);
    const result = counter;
    console.log(result); // 1
  }

因为 counter 更像是保存的一份快照,我们调用 setCounter() 函数的时候并不会去更新 counter 的值,所以这种方式是不能正确获取的。

相关推荐
qczg_wxg5 小时前
高阶组件介绍
开发语言·javascript·react native·ecmascript
光影少年1 天前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划
qczg_wxg2 天前
React Native的动画系统
javascript·react native·react.js
qczg_wxg2 天前
React Native常用的API
react native
Winson℡2 天前
在 React Native 层禁止 iOS 左滑返回(手势返回/手势退出)
react native·react.js·ios
卸任2 天前
从0到1搭建react-native自动更新(OTA和APK下载)
前端·react native·react.js
wayne2142 天前
「原生 + RN 混合工程」一条命令启动全攻略:解密 react-native.config.js
android·react native
qczg_wxg3 天前
ReactNative系统组件四
javascript·react native·react.js
ZTStory4 天前
JS 处理生僻字字符 sm4 加密后 Java 解密字符乱码问题
javascript·掘金·金石计划
光影少年4 天前
webpack打包优化都有哪些
前端·webpack·掘金·金石计划