面试官:这个思路不错,但是如果项目中有很多按钮都需要这样处理,你会怎么做?
候选人:额...每个按钮都写一遍 loading 状态管理?
面试官:那样就会有很多重复代码,有没有想过怎么封装呢?
到这里也卡掉了很多人
解决方案
我们可以封装一个自定义 Hook
import {useState,useCallback,useRef} from 'react'
function useLock(asyncFn) {
const [loading, setLoading] = useState(false)
const asyncFnRef = useRef(null)
asyncFnRef.current = asyncFn
const run = useCallback(async (...args) => {
if(loading) return
setLoading(true)
try {
await asyncFnRef.current(...args)
} finally {
setLoading(false)
}
}, [loading])
return [loading,run]
}
import {Button as AntButton} from 'antd'
const Button = ({onClick,...props})=>{
const {loading, run} = useLock(onClick || (()=> {}))
return <AntButton loading={loading} {...props} onClick={run}></button>
}
const Demo = () => {
const handleSubmit = async () => {
// 模拟异步请求
await new Promise(resolve => setTimeout(resolve, 2000))
console.log('提交成功')
}
return (
<Button onClick={handleSubmit}>
提交
</Button>
)
}
可以看到 在 handleSubmit 执行的时候 Button 会自动添加 loading, 在请求完成后 loading 会自动变为 false。
方案优势
- 零侵入性 :使用方式与普通按钮完全一致
- 自动处理 :自动管理 loading 状态,无需手动控制
希望这篇文章对你有帮助!如果觉得有用,别忘了点个赞 👍
讨论
你在项目中是如何处理按钮重复点击的问题的?欢迎在评论区分享你的解决方案!
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。