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 的值,所以这种方式是不能正确获取的。

相关推荐
jxm_csdn9 小时前
Expo Go 本地命令行编译 apk(Ubutnu22.04)
react native
红尘散仙20 小时前
一套 Rust 核心,跑通 Tauri + React Native
react native·react.js·rust
光影少年1 天前
react的 useState 原理、批量更新机制
前端·react.js·掘金·金石计划
诚实可靠王大锤2 天前
React Native 输入框与按钮焦点冲突解决方案(rn版本0.70.3)
前端·javascript·react native·react.js
sealaugh325 天前
react native(学习笔记第四课) 英语打卡微应用(3)-ocr的文字转化成语音文件(tts)
笔记·学习·react native
wordbaby6 天前
如何封装一个生产级的 React Native 分页列表 Hook
前端·react native·react.js
光影少年8 天前
react 单向数据流理解
前端·react.js·掘金·金石计划
沐言人生8 天前
ReactNative 源码分析5——ReactActivity之启动RN应用
android·react native
沐言人生9 天前
ReactNative 源码分析4——ReactActivity之加载JSBundle
android·react native
沐言人生10 天前
ReactNative 源码分析3——ReactActivity之初始化RN应用
android·react native