示例详解react中useState的用法

useState

useState 通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 state。useState
会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。它类似 class 组件的
this.setState,但是它不会把新的 state 和旧的 state 进行合并。

接下来通过一个示例来看看怎么使用 useState。

有这么一个需求:需要在 iframe 中加载外部网页

初始的代码我们通过 函数式组件 来实现这个需求,只需要简单的渲染一个 iframe

import React, { useState } from 'react';

import styles from './index.less';

function Link(props) {
  const { match: { params: { link = '' } = {} } = {} } = props;
  const enCodeUrl = decodeURIComponent(link);
  const url = enCodeUrl.startsWith('http') ? enCodeUrl : `http://${enCodeUrl}`;
  return (
    <React.Fragment>
        <iframe
          title={link}
          src={url}
          style={{ width: '100%', height: '100%', verticalAlign: 'top' }}
          frameBorder="0"
        />
    </React.Fragment>
  );
}

export default Link;

新的需求来了,我们需要给页面添加一个 loading 效果,实现的方式很简单,监听 iframe 的 load 事件 来设置loading的开始和结束

为了实现这个需求,我们需要存放loading的状态而函数式组件是没有自有状态的,我们得改造成 class 组件:

import React from 'react';
import { Spin } from 'antd';

import styles from './index.less';

export default class Link extends React.Component {
  state = {
    // 存放loading状态
    iLoading: true,
  };

  linkLoad() {
    // 更新loading
    this.setState({ iLoading: false });
  }

  render() {
    const { match: { params: { link = '' } = {} } = {} } = this.props;
    const { iLoading } = this.state;
    const enCodeUrl = decodeURIComponent(link);
    const url = enCodeUrl.startsWith('http') ? enCodeUrl : `http://${enCodeUrl}`;
    return (
      <React.Fragment>
        <Spin spinning={iLoading} wrapperClassName={styles['iframe-loading']}>
          <iframe
            onLoad={this.linkLoad.bind(this)}
            title={link}
            src={url}
            style={{ width: '100%', height: '100%', verticalAlign: 'top' }}
            frameBorder="0"
          />
        </Spin>
      </React.Fragment>
    );
  }
}

为了实现一个页面的loading,我们需要去使用class,同时还需要bind绑定this等繁琐行为,这只是一个简单的需求,而我们却可以通过hooks来解决这些问题,同时还能解决组件间状态复用的问题,我们使用useState来实现

导入 useState
import React, { useState } from 'react';
定义状态
  // useState 的参数为状态初始值,setInitLoading为变更状态值的方法
  const [initLoading, setInitLoading] = useState(true);
更新状态
onLoad={() => setInitLoading(false)}
完整代码如下:

import React, { useState } from 'react';
import { Spin } from 'hzero-ui';

import styles from './index.less';

function Link(props) {
  const { match: { params: { link = '' } = {} } = {} } = props;
  const [initLoading, setInitLoading] = useState(true);
  const enCodeUrl = decodeURIComponent(link);
  const url = enCodeUrl.startsWith('http') ? enCodeUrl : `http://${enCodeUrl}`;
  return (
    <React.Fragment>
      <Spin spinning={initLoading} wrapperClassName={styles['iframe-loading']}>
        <iframe
          onLoad={() => setInitLoading(false)}
          title={link}
          src={url}
          style={{ width: '100%', height: '100%', verticalAlign: 'top' }}
          frameBorder="0"
        />
      </Spin>
    </React.Fragment>
  );
}

export default Link;

下面看看useState注意事项

useState 的参数

useState 的参数可以是基本类型,也可以是对象类型,在更新对象类型时,切记要合并旧的状态,否则旧的状态会丢失

const [params, setParams] = useState({
  rotate: 0,
  color: "#000000"
});

const handleInputChange = event => {
  const target = event.target;
  setParams({
    ...params,
    [target.name]: target.value
  });
};

状态依赖

如果当前的状态需要根据最后一次更新的状态的值计算出来,则给更新状态的函数传递一个函数,此函数的第一个参数即为最后一次更新的值,然后把计算后的结果做为返回值返回出去。

总结

利用 useState hook 可以让函数式组件拥有状态管理特性,它与传统的 class 组件的状态管理类似,但是更加简洁,不用频繁的使用 this。在后面的文章中将会介绍到如何结合其他的 hooks 对业务逻辑进行抽离以使组件代码和 hooks 代码各司其职。

(0)

相关推荐

  • react-redux中connect的装饰器用法@connect详解

    最近在琢磨react中的一些小技巧,这篇文章记录一下在redux中用装饰器来写connect. 通常我们需要一个reducer和一个action,然后使用connect来包裹你的Component.假设你已经有一个key为main的reducer和一个action.js. 我们的App.js一般都这么写: import React from 'react' import {render} from 'react-dom' import {connect} from 'react-redux' i

  • 详解在React项目中安装并使用Less(用法总结)

    less的安装配置 安装react-app-rewired,react-app-rewire-less,babel-plugin-import插件 执行命令: npm install react-app-rewired --save-dev npm install react-app-rewire-less --save-dev npm install babel-plugin-import --save-dev 配置package.json文件 找到scripts属性,修改start的值为re

  • 详解Python的Twisted框架中reactor事件管理器的用法

    铺垫 在大量的实践中,似乎我们总是通过类似的方式来使用异步编程: 监听事件 事件发生执行对应的回调函数 回调完成(可能产生新的事件添加进监听队列) 回到1,监听事件 因此我们将这样的异步模式称为Reactor模式,例如在iOS开发中的Run Loop概念,实际上非常类似于Reactor loop,主线程的Run Loop监听屏幕UI事件,一旦发生UI事件则执行对应的事件处理代码,还可以通过GCD等方式产生事件至主线程执行. 上图是boost对Reactor模式的描绘,Twisted的设计就是基于

  • React-Native中一些常用组件的用法详解(一)

    前言 本文为大家介绍一下React-Native中一些常用的组件,由于对ES6的语法并没有完全掌握,这里暂时用ES5和ES6混用的语法. View组件 View是一个支持Flexbox布局.样式.一些触摸处理.和一些无障碍功能的容器,并且它可以放到其它的视图里,也可以有任意多个任意类型的子视图. View的设计初衷是和StyleSheet搭配使用,这样可以使代码更清晰并且获得更高的性能.尽管内联样式也同样可以使用. View的常用样式设置 flex布局样式 backgroundColor:背景颜

  • React教程之Props验证的具体用法(Props Validation)

    Props验证对于组件的正确使用是一种非常有用的方式.它可以避免随着你的应用的程序越来越复杂从而出现很多的bug和问题.并且,它还可以是你的程序变得更易读. 那如何对Props进行验证呢,其实很简单,React为我们提供了PropTypes以供验证使用.当我们向Props传入的数据无效(也就是向Props传入的数据类型和验证的数据类型不符)就会在控制台发出警告信息. 看下面的例子 var Propsva = React.createClass({ propTypes: { optionalArr

  • 详解关于react-redux中的connect用法介绍及原理解析

    关于react-redux的一个流程图 流程图 connect用法介绍 connect方法声明: connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options]) 作用:连接React组件与 Redux store. 参数说明: mapStateToProps(state, ownProps) : stateProps 这个函数允许我们将 store 中的数据作为 props 绑定到组件上. const mapSta

  • 示例详解react中useState的用法

    useState useState 通过在函数组件里调用它来给组件添加一些内部 state.React 会在重复渲染时保留这个 state.useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数.它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并. 接下来通过一个示例来看看怎么使用 useState. 有这么一个需求:需要在 iframe 中加载外部网页. 初始的代码我们通过

  • 详解C++中mutable的用法

    代码编译运行环境:VS2017+Win32+Debug mutalbe的中文意思是"可变的,易变的",是constant(即C++中的const)的反义词.在C++中,mutable也是为了突破const的限制而设置的,被mutable修饰的变量将永远处于可变的状态. mutable的作用有两点: (1)保持常量对象中大部分数据成员仍然是"只读"的情况下,实现对个别数据成员的修改: (2)使类的const函数可以修改对象的mutable数据成员. 使用mutable

  • 详解React中共享组件逻辑的三种方式

    废话少说,这三种方式分别是:render props.高阶组件和自定义Hook.下面依次演示 假设有一个TimeOnPage组件专门用来记录用户在当前页面停留时间,像这样: const TimeOnPage = () => { const [second, setSecond] = useState(0); useEffect(() => { setTimeout(() => { setSecond(second + 1); }, 1000); }, [second]); return

  • 详解React中key的作用

    要了解React中key的作用,可以从key的取值入手,key的取值可以分为三种,不定值.索引值.确定且唯一值 在下面的代码中,key的取值是不定值(Math.random()) 问题: 点击按钮的时候,span的颜色会变成红色吗? import React, { useState } from 'react'; function App() { const [initMap, setInitMap] = useState([1,2,3,4]); const handleClick = () =

  • 一文详解Python中复合语句的用法

    目录 Python复合语句 1.if 语句 2.while 语句 3.for 语句 4.try 语句 5.with 语句 6.match 语句 Python复合语句 复合语句是包含其它语句(语句组)的语句:它们会以某种方式影响或控制所包含其它语句的执行.通常,复合语句会跨越多行,虽然在某些简单形式下整个复合语句也可能包含于一行之内. if.while和for语句用来实现传统的控制流程构造.try语句为一组语句指定异常处理和/和清理代码,而with语句允许在一个代码块周围执行初始化和终结化代码.函

  • 详解python中静态方法staticmethod用法

    在开发的时候, 可以使用类对方法进行封装,如果某一个方法需要访问到对象的实例属性,可以把这个方法封装成一个实例方法.如果某一个方法不需要访问对象的实例属性,但是需要访问到类的类属性,这个时候就可以考虑把这个方法封装成一个类方法.一个实例方法, 一个类方法,这是两种方法类型,但是在开发中还有一种情况,如果要封装的某一个方法,既不需要访问到对象的实例属性,也不需要访问类的类属性,这个时候就可以考虑把这个方法封装成一个静态方法. 在开发中,如果类中的某个方法既不需要访问实例属性或者调用实例方法,同时也

  • 详解Reactor中Context的用法

    目录 一.使用介绍 二.源码解读 三.如何桥接现有的ThreadLocal系统 四.总结 在响应式编程中,多线程异步性成为天然的内在,多线程之间的切换也成为原生的,在处理一个数据流Flux/Mono时,基本无法知道是运行在哪个线程上或哪个线程池里,可以说,每一个操作符operator以及内部的函数都可能运行在不同的线程上.这就意味着,以前用ThreadLocal来作为方法间透明传递共享变量的方式不再行得通.为此,Reactor提供了Context来替代ThreadLocal实现一个跨线程的共享变

  • 详解C# 中Session的用法

    Session模型简介 在学习之前我们会疑惑,Session是什么呢?简单来说就是服务器给客户端的一个编号.当一台WWW服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站.当每 个用户首次与这台WWW服务器建立连接时,他就与这个服务器建立了一个Session,同时服务器会自动为其分配一个SessionID,用以标识这个用 户的唯一身份.这个SessionID是由WWW服务器随机产生的一个由24个字符组成的字符串,我们会在下面的实验中见到它的实际样子. 这个唯一的SessionID是有

  • 详解Golang中Channel的用法

    如果说goroutine是Go语言程序的并发体的话,那么channels则是它们之间的通信机制.一个channel是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值信息. 1 创建channel 每个channel都有一个特殊的类型,也就是channels可发送数据的类型.一个可以发送int类型数据 的channel一般写为chan int.使用内置的make函数,如果第二个参数大于0,则表示创建一个带缓存的channel. ch := make(chan in

  • 详解React中的不可变值

    什么是不可变值 函数式编程是指程序里面的函数和表达式都能像数学中的函数一样,给定了输入值,输出是确定的.比如 let a = 1; let b = a + 1; => a = 1 b = 2; 变量b出现,虽然使用了变量a的值,但是没有修改a的值. 再看我们熟悉的react中的代码,假如初始化了this.state = { count: 1 } componentDidMount() { const newState = { ...state, count: 2 }; // { count: 2

随机推荐