# React 实现异步按钮
AsyncButton 组件实现思路:
- 如果 onClick 事件是异步的 (返回 Promise),就需要 Loading 状态
- 除了要处理 resolve 还别忘了处理 reject
# 例子:业务自行维护 Loading 状态
import { Button } from 'antd'
import { useState } from 'react';
import { login } from './services'
function Loading() {
const [loading, setLoading] = useState(false)
async function handleLogin() {
setLoading(true)
try {
await login()
} finally {
setLoading(false)
}
}
return (
<div>
<Button onClick={handleLogin} loading={loading}>Login</Button>
</div>
);
}
export default Loading;
# 例子:封装 AsyncButton 组件
import { Button } from 'antd'
import { useState } from 'react';
function AsyncButton({ onClick, children }) {
const [loading, setLoading] = useState(false)
async function handleClick() {
setLoading(true)
try {
await onClick()
} finally {
setLoading(false)
}
}
return <Button onClick={handleClick} loading={loading}>
{children}
</Button>
}
export default AsyncButton
# 例子:在列表页中使用 AsyncButton
import React from 'react'
import { Table } from 'antd'
import { getAllUsers, deleteUser } from './services'
import AsyncButton from './AsyncButton'
class ListDemo extends React.Component {
constructor(props) {
super(props)
this.state = {
users: [],
loading: false
}
this.columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a>{text}</a>,
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Action',
key: 'action',
render: (text, record) => (
<AsyncButton onClick={() => this.handleDeleteUser(record.id)}>Delete</AsyncButton>
),
},
]
}
async componentDidMount() {
await this.fetchData()
}
async fetchData() {
this.setState({ loading: true })
const users = await getAllUsers()
this.setState({ users, loading: false })
}
async handleDeleteUser(id) {
await deleteUser(id)
this.fetchData()
}
render() {
return <Table
columns={this.columns}
dataSource={this.state.users}
loading={this.state.loading}
rowKey="id"
/>
}
}
export default ListDemo