react hooks - useState 使用

作者: konnga | 来源:发表于2019-07-03 22:49 被阅读49次

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

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来实现。

  1. 导入 useState
import React, { useState } from 'react';
  1. 定义状态
  // useState 的参数为状态初始值,setInitLoading为变更状态值的方法
  const [initLoading, setInitLoading] = useState(true);
  1. 更新状态
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 使得我们的代码更加轻便,同时更容易理解和阅读。

相关文章

网友评论

    本文标题:react hooks - useState 使用

    本文链接:https://www.haomeiwen.com/subject/kjuhhctx.html