useState
useState 通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 state。useState
会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。它类似 class 组件的
this.setState,但是它不会把新的 state 和旧的 state 进行合并。
接下来通过一个示例来看看怎么使用 useState。
有这么一个需求:需要在 iframe 中加载外部网页。
初始的代码我们通过 函数式组件 来实现这个需求,只需要简单的渲染一个 iframe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 导入 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 的参数可以是基本类型,也可以是对象类型,在更新对象类型时,切记要合并旧的状态,否则旧的状态会丢失
1 2 3 4 5 6 7 8 9 10 11 12 | 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 代码各司其职。
- 本文固定链接: https://zxbcw.cn/post/214169/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)