react hooks之初体验

官方实例

神奇传送门

前因

在项目里因为是c端高度定制化,所以没有使用类似ant designmodal组件,所以我自己重新封装了rc-dialog

我用了代理模式来设计这个组件,因为多数是对样式上的调整,所以很多多余的api我都做了收口,只暴露几个项目里可能用到的api

因为涉及的逻辑就不在该组件内部了,所以我准备用函数组件去做,但是因为它原生关闭按钮是一个放在伪类里的x,不符合项目里UI的设计,所以我修改了它原生关闭按钮的样式,放上了我自己的icon,于是这里的关闭逻辑就需要自己重写了

因为存在了要自己封装的点击按钮关闭的逻辑,但我又很想用函数组件,所以用了react hooks


经过

很理想很天真的写了如下代码:

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
import React, { useState, useEffect } from 'react';
import Dialog from 'rc-dialog';
import styles from './styles.less';

function Modal (props) {
const [visible, setVisible] = useState(props.visible);

return (
<Dialog
destroyOnClose={props.destroyOnClose}
visible={visible}
wrapClassName={`${styles.modalWrap} ${props.wrapClassName}`}
className={props.className}
animation={props.animationName}
onClose={props.onClose}
closable={props.closable}
afterClose={props.afterClose}
title={
<i onClick={() => setVisible(false)} className="iconfont iconClose" />
}
>
{props.children}
</Dialog>
);
};

Modal.defaultProps = {
destroyOnClose: false,
visible: false,
closable: false,
};

看上去真的没什么问题,但是用起来就暴露了

首先因为visible的属性是通过props从外部传进来,说明在外面也存在逻辑控制这个Dialog的显示与否

而在使用useState的时候,初始化虽然把props.visible赋值到了state状态里

但是!!! 忘记了useState只在初始化的时候执行,当你的visible用的是state的值时props里的值改变了并不会让组件re-render!!!好气


后果

于是我加上了useEffect方法 作用很多我也赘述不完,只能看官网和别人踩过的坑

用法:

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
function Modal (props) {
const [visible, setVisible] = useState(props.visible);
useEffect(() => {
setVisible(props.visible);
},[props.visible])
return (
<Dialog
destroyOnClose={props.destroyOnClose}
visible={visible}
wrapClassName={`${styles.modalWrap} ${props.wrapClassName}`}
className={props.className}
animation={props.animationName}
onClose={props.onClose}
closable={props.closable}
afterClose={props.afterClose}
title={
<i onClick={() => {
setVisible(false)
props.handleClose()
}} className="iconfont iconClose" />
}
>
{props.children}
</Dialog>
);
};

useEffect里,监听props里的visible是否改变了,如果改变了就去调用对应的修改state的方法

有一个注意点就是useEffect的第二个参数一定要是一个数组!!!并且在点击icon的时间要调用外部的props的方法通知外部组件状态的修改