使用react hooks 和 ant-design 遇到的问题
功能介绍:实现登录,博客的增删改查
技术点: 前端使用react hooks编写函数式组件,create-react-app创建项目,使用ant-design,后端使用node.js原生实现
此文章只针对前端部分遇到的一些问题做一个记录,如有错误,请指出。
一、 ant-design:
-
table样式问题:一定要给装table的容器设置一个高度100%,否则样式会出现奇奇怪怪的错误。
正如博客列表需要表格来展示,这里把table放在一个容器里面,因为没有给容器设置高度100%,最后是这样的
badTable.png
显然不是我们要的结果,只有给容器加上height:100%才能正常显示。
注意:1.当我们想要表格实现自适应时,必须给<Table />组件的tableLayout属性赋值为"fixed",如果是"auto",表格的宽度就无法填满容器。
2.
这里报一个warning,他说每一个child在一个列表中应该有一个唯一的"key",在ant-design的官方文档中有一个注意点:

这时加上<Table rowKey={record => record.id} />
,就可以了。
- Popcomfirm气泡确认框
再一个就是删除某一行的操作,初始代码是这样的
... 省略的代码
export default function BlogList(props) {
... 省略的代码
// 删除博客
const deleteBlog = async (data) => {
let id = data.id
const result = await axios.post('http://localhost:5000/api/blog/del?id='+ id)
if (result.data.data === 0) {
message.success('Successfully delete!')
props.getBlogList()
} else {
history.push('/login')
message.error('Failure! Please login in first!')
}
}
const columns = [
{...}, {...}, // 省略,此处只写出关键代码
{
title: "Action",
dataIndex: "action",
key: "action",
render: (text, record) => (
<Space size="middle">
<Button type="ghost" icon={<EditOutlined />} onClick={() => onCreate(record)}>Edit</Button>
<Button type="ghost" icon={<DeleteOutlined />} onClick={() => deleteBlog(record)}>Delete</Button>
</Space>
)
}
]
return (
<div style={{height: '100%'}}>
<Table
dataSource={props.list}
columns={columns}
rowKey={record => record.id}
tableLayout="fixed"
size="small"
></Table>
</div>
)
}
上述代码可以实现删除操作,但是一般来说要删除某一行,点击的时候应该还得有一个待确认的操作,确认删除或者取消删除,看antd文档,找到一个Popconfirm气泡确认框
。
修改代码:
... 省略的代码
export default function BlogList(props) {
... 省略的代码
// 删除博客
// const deleteBlog = async (data) => {
// let id = data.id
// const result = await axios.post('http://localhost:5000/api/blog/del?id='+ id)
// if (result.data.data === 0) {
// message.success('Successfully delete!')
// props.getBlogList()
// } else {
// history.push('/login')
// message.error('Failure! Please login in first!')
// }
// }
// 确认删除博客
const handleOnConfirm = async () => {
// 2. 将原先deleteBlog事件的一系列操作复制到onConfirm事件中
let id = data.id
const result = await axios.post('http://localhost:5000/api/blog/del?id='+ id)
if (result.data.data === 0) {
message.success('Successfully delete!')
props.getBlogList()
} else {
history.push('/login')
message.error('Failure! Please login in first!')
}
}
const columns = [
{...}, {...}, // 省略,此处只写出关键代码
{
title: "Action",
dataIndex: "action",
key: "action",
render: (text, record) => (
<Space size="middle">
<Button type="ghost" icon={<EditOutlined />} onClick={() => onCreate(record)}>Edit</Button>
// ----------- changed code -----------
<Popconfirm
title="Are you sure delete this task?"
onConfirm={handleOnConfirm} // 确认时的操作
onCancel={cancel} // 取消时的操作
okText="Yes"
cancelText="No"
>
<Button
type="ghost"
icon={<DeleteOutlined />}
// onClick={() => deleteBlog(record)} // 1.注释掉
>Delete</Button>
</Popconfirm>
// ----------- changed code -----------
</Space>
)
}
]
return (
<div style={{height: '100%'}}>
<Table
dataSource={props.list}
columns={columns}
rowKey={record => record.id}
tableLayout="fixed"
size="small"
></Table>
</div>
)
}
上述代码可以看到,我们想要的效果是分两步操作:
- 当我们点击Delete按钮的时候,弹出Popconfirm确认框
- 当我们点击确认框里面的确认按钮时,才进行发起删除请求的操作 或者 当我们点击取消时,取消删除操作
那我们就得
-
把Button的点击事件注释掉,然后deleteBlog这个事件已经没用了,
-
我们可以把它里面的操作放到onConfirm事件里面
-
这时有个问题,onComfirm里面需要获取id,也就是只有获取到当前行的内容,才能获取到该行的id
-
这时就得修改onComfrim操作了,不要返回一个handleOnConfirm函数,因为你如果是这样写,直接传参,那相当于是直接调用,页面加载完成后会马上把你所有的博客数据一条一条全删了
onConfirm={handleOnConfirm(record)} // 如果直接传参数,会删除所有数据
怎么解决?我们想要的是他延迟执行,而不是要他马上执行,这时我们就需要返回一个匿名函数。
onConfirm={() => {handleOnConfirm(record)}}
补充一个注意点:我们是需要点击Button时,弹出确认框,所以我们要把Button放在Popconfirm里面。
网友评论