@
jklopsdfw 简单回复一下,可能不是很对哈,多指教。
1. useState 用在有状态组件,状态更新后 React 就会自上而下检索更新相关联的组件。
useRef 用于保存 React 实例 或者是存储任何数据,他改变之后是不会触发组件渲染的,在组件生命周期内其保存的数据都不会改变,要手动赋值。
2. useEffect 意味着副作用,当 deps list 中的 state 变更后会在渲染完成后执行。适合放一些在 state 变更需要自动触发的逻辑。要注意的就是,他的执行时机是在浏览器渲染完成之后,其他场景都可以。
deps list 确实就是 react 现阶段的硬伤,依赖项很容易就特别多。让 deps list 真实的反应业务逻辑,做好状态的细粒度管理。
1. 是组件按职责抽象拆分好,状态适当的聚合。
2. 得当的命名。
3. 写注释哈哈,有些 effect 中逻辑,的确就是要排除某个 state 的。
4. useEffect 内部的回调函数,在封装时与状态无关的的善用 useRef 保存,与状态有关的善用 useCallback ,这样可以将 deps list 拆分到别的函数中。
平时写的啊大部分是业务里的,不方便贴了,我贴一个倒计时组件的,相对通用点的。就是一个弹出层,打开必须等倒计时结束才能关闭。
3. useEffectEvent 我其实没听过哈哈,不太懂是个啥。。望指教
```ts
type PorpOptions = {
afterClose?: () => void
count?: number
}
type Props = PorpOptions & IModalProps<boolean>
const ClearCacheTipWindow = ({ visible, hidden, afterClose, count = 3, ...props }: Props) => {
const [countdown, setCountdown] = React.useState(count)
const intervalRef = React.useRef<NodeJS.Timer>()
useEffect(() => {
if (visible) setCountdown(count)
}, [count, visible])
useEffect(() => {
let canUpdate = true
if (countdown !== 0) {
intervalRef.current = setInterval(() => {
if (count !== 0) {
canUpdate && setCountdown(c => --c)
}
}, 1000)
}
return () => {
canUpdate = false
clearInterval(intervalRef.current)
}
}, [count, countdown])
// 倒计时文本
const remainCount = React.useMemo(() => {
return countdown > 0 ? <>{countdown}s</> : null
}, [countdown])
// 可否点击以关闭弹层
const disabled = React.useMemo(() => {
return countdown !== 0
}, [countdown])
return (
<Modal
title='保存成功'
afterClose={() => afterClose?.()}
width={480}
centered
getContainer={false}
closable={false}
maskClosable={false}
keyboard={false}
visible={visible}
onCancel={() => hidden(false)}
footer={[
<Button key='primary' disabled={disabled} onClick={() => hidden(true)} type='primary'>
已完成上述操作{remainCount}
</Button>
]}
{...props}
>
<>巴拉巴拉的内容<>
</Modal>
)
}
```