刚刚入门react,通过视频学习,做一个简单的react表格功能实现。功能满足对表格数据进行增删改,数据来源于后端接口。交互也与后端接口进行!
话不多说,直接看效果!



接口设置了30%的概率报错,出现错误多刷新几次。
这是后端接口地址 https://public-api-v1.aspirantzhang.com/
浏览器可以直接看到接口数据

项目的搭建是参照于umi官网的快速上手进行搭建的,想要试试的小伙伴可以先将项目搭建起来!https://umijs.org/zh-CN/docs/getting-started

我们的项目主要集中在page下的users文件夹中的内容!
在page下新建uses文件夹
新建这几个文件
我们在components文件夹下放的文件的组件,UserModal,为弹出框组件
import React,{useEffect,FC} from "react";
import {Modal, Button ,Form,Input} from 'antd';
import {SingleUserType,FormValues} from '../data'
interface UserModalProps{
visible:boolean;
record:SingleUserType|undefined
closeHandeler:()=>void
onFinish:(values:FormValues)=>void
}
const UserModal :FC<UserModalProps> = (props)=>{
const[form]=Form.useForm();
const {visible,record,closeHandeler,onFinish} = props
// useEffect(参数1,参数2) 当参数2发生改变时,执行参数1 参数1为函数,参数2为数组
useEffect(()=>{
if(record==undefined){
form.resetFields();
}
else{
form.setFieldsValue(record);
}
},[visible])
const onOk=()=>{
form.submit()
}
const onFinishFailed = () => {
console.log('Submit failed!');
};
return(
<div>
<Modal title="基本信息"
visible={visible}
onOk={onOk}
onCancel={closeHandeler}
forceRender>
<Form
name="basic"
form={form}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item
label="姓名"
name="name"
rules={[
{
required: true,
message: 'Please input your name!',
},
]}
>
<Input />
</Form.Item>
<Form.Item label="邮箱" name="email">
<Input />
</Form.Item>
<Form.Item label="创建时间" name="create_time">
<Input />
</Form.Item>
<Form.Item label="状态" name="status">
<Input />
</Form.Item>
</Form>
</Modal>
</div>
)
}
export default UserModal
在users文件夹下index为主页面,data.a为数据类型,model为模块文件,service为交互后端文件
index.tsx
import React,{ FC, useState} from 'react';
import { Table, Space,Modal, Button,Popconfirm,Tag } from 'antd';
import ProTable, { TableDropdown ,ProColumns, ActionType} from '@ant-design/pro-table';
import { connect,Dispatch, Loading,UserState } from 'umi';
import UserModal from './compoents/UserModal';
import {getRemoteList} from './service'
import {SingleUserType,FormValues} from './data.d'
interface UserPageProps{
users:UserState,
dispatch:Dispatch,
userListLoading:boolean,
}
const UserListPage:FC<UserPageProps> =({users,dispatch,userListLoading})=>{
const [modalVisible,setModalVisible]=useState(false)
const [record,setRecord]=useState<SingleUserType|undefined>(undefined)
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
render:( text :string) => <a>{text}</a>,
},
{
title: '邮箱',
dataIndex: 'email',
key: 'email',
render: ( text :string) => <a>{text}</a>,
},
{
title: '创建时间',
dataIndex: 'create_time',
key: 'create_time',
},
{
title: '更新时间',
dataIndex: 'update_time',
key: 'update_time',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render:tag=>{
let color='#87d068'
if(tag!==1){
color = tag == 2 ? '#108ee9' : 'green'
}
else{
color='#f50'
}
return <Tag color={color} key={tag}>状态:{tag}</Tag>
}
},
{
title: '操作',
key: 'action',
render: (text:string,record:SingleUserType) => (
<Space size="middle">
<a onClick={()=>{
editHandler(record)
}}>编辑</a>
<Popconfirm
title="确定要删除这条信息吗?"
onConfirm={()=>{
confirm(record)
}}
okText="Yes"
cancelText="No"
>
<a href="#">删除</a>
</Popconfirm>
</Space>
),
},
];
const editHandler=(record:SingleUserType)=>{
console.log(record)
setModalVisible(true);
setRecord(record);
}
const closeHandeler=()=>{
setModalVisible(false)
}
// 编辑确认
const onFinish = (values:FormValues) => {
let id =0
if(record){
id=record.id;
}
if(id){
console.log('edit')
dispatch({
type:'users/edit',
payload:{
id,
values
}
})
}
else{
console.log('add')
dispatch({
type:'users/add',
payload:{
values
}
})
}
setModalVisible(false)
};
// 删除确定
const confirm=(record:SingleUserType)=>{
const id=record.id
dispatch({
type:'users/delete',
payload:{
id
}
})
}
const addHandler=()=>{
setModalVisible(true)
setRecord(undefined)
}
const requestHandler= async ({pageSize,current})=>{
console.log(pageSize,current)
const users=await getRemoteList();
return {
data:users.data,
success:true,
total:users.meta.total,
}
}
return(
<div className='list-table'>
<Button type="primary" onClick={addHandler}>添加</Button>
<ProTable
columns={columns}
dataSource={users.data}
rowKey='id'
loading={userListLoading}
request={requestHandler}
search={false}
/>
<UserModal visible={modalVisible} closeHandeler={closeHandeler} record={record} onFinish={onFinish}></UserModal>
</div>
)
};
const mapStateToProps = ({users,loading}:{users:UserState,loading:Loading})=>{
console.log(loading)
return{
users,
userListLoading:loading.models.users,
}
}
export default connect(mapStateToProps)(UserListPage)
data.d.ts
export interface SingleUserType{ "id": number, "name": string, "email": string , "create_time": string , "update_time": string, "status": number } export interface FormValues{ [name:string]:any; }
model.ts
import {Reducer,Effect,Subscription} from 'umi'
import users from '.';
import {getRemoteList,editRecord,deleteRecord,addRecord} from './service'
import {SingleUserType} from './data.d'
export interface UserState{
data:SingleUserType[],
meta:{
total:number;
per_page:number;
page:number;
}
}
interface UserModelType{
namespace:'users';
state:UserState;
reducers:{
getList:Reducer<UserState>
};
effects:{
getRemote:Effect
edit:Effect
delete:Effect
add:Effect
};
subscriptions:{
setup:Subscription;
};
}
const UserModel: UserModelType = {
// 命名空间,也叫标识名
namespace:'users',
// 仓库数据初始值
state:{
data:[],
meta:{
total:0,
per_page:5,
page:1,
}
},
// 同步
//action相当于是{type,payload} type:函数名 payload:数据
reducers:{
getList(state,{payload}){
console.log("reducer here")
return payload;
}
},
// 异步 返回的是一个viod 只能通过reduces返回数据
effects:{
// 异步函数前要加*
*getRemote(action,{put,call}){
const data = yield call (getRemoteList)
yield put({
type:'getList',
payload: data
})
},
*edit({payload:{id,values}},{put,call}){
const data = yield call (editRecord,{id,values})
yield put({
type:'getRemote'
})
},
*delete({payload:{id}},{put,call}){
const data = yield call (deleteRecord,{id})
yield put({
type:'getRemote'
})
},
*add({payload:{values}},{put,call}){
const data = yield call (addRecord,{values})
yield put({
type:'getRemote'
})
},
},
// 订阅
subscriptions:{
setup({dispatch,history}){
return history.listen((location,action)=>{
if(location.pathname=='/users'){
console.log("subscription here")
dispatch({
type:'getRemote',
});
}
});
}
}
};
// 导出model
export default UserModel;
service.ts
import { response } from "@umijs/deps/compiled/express";
import { request } from "umi"
import { message } from 'antd';
import { FormValues } from "./data";
export const getRemoteList =async () => {
return request('/api/users',{
method:'get',
}).then(function(response){
console.log("update ok")
return response
})
.catch(function(error){
console.log(error);
})
}
export const editRecord =async ({id,values}:{id:number,values:FormValues}) => {
return request(`/api/users/${id}`,{
method:'put',
data:values
}).then(function(response){
message.success('修改成功!');
})
.catch(function(error){
message.error('修改失败!');
})
}
export const deleteRecord =async ({id}:{id:number}) => {
return request(`/api/users/${id}`,{
method:'delete',
}).then(function(response){
message.success('删除成功!');
})
.catch(function(error){
message.error('删除失败!');
})
}
export const addRecord =async ({values}:{values:FormValues}) => {
return request(`/api/users/`,{
method:'post',
data:values
}).then(function(response){
message.success('添加成功!');
})
.catch(function(error){
message.error('添加失败!');
})
}
其中路由配置了代理,可以参考我上一篇发布的文章https://www.cnblogs.com/yqPhare/p/16199595.html
浙公网安备 33010602011771号