官方实例
神奇传送门
前因
在项目里因为是c端高度定制化,所以没有使用类似ant design
的modal
组件,所以我自己重新封装了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的方法通知外部组件状态的修改